腾讯云网站建设的步骤过程,sem竞价推广,营销型高端网站建设价格,wordpress中页面编辑if else嵌套
这次来研究if else嵌套在汇编中的表现形式#xff0c;本次以获取三个数中最大的数这个函数为例子#xff0c;分析if else的汇编形式
求三个数中的最大值
首先贴上代码#xff1a;
#include stdafx.hint result0;
int getMax(int i,int j,int k)…if else嵌套
这次来研究if else嵌套在汇编中的表现形式本次以获取三个数中最大的数这个函数为例子分析if else的汇编形式
求三个数中的最大值
首先贴上代码
#include stdafx.hint result0;
int getMax(int i,int j,int k){if(ij){if(ik){return i;}else{return k;}}else{if(jk){return j;}else{return k;}}
}int main(int argc, char* argv[])
{resultgetMax(1,2,3);printf(%d\n,result);resultgetMax(1,3,2);printf(%d\n,result);resultgetMax(2,1,3);printf(%d\n,result);resultgetMax(2,3,1);printf(%d\n,result);resultgetMax(3,1,2);printf(%d\n,result);resultgetMax(3,2,1);printf(%d\n,result);return 0;
}先验证执行的结果是正确的 确认可以函数是可以取出三个数的最大值的于是开始分析该函数
为方便观看将多余的验证删去直接改为
getMax(1,2,3);汇编代码
然后我们观察汇编代码
函数外部
28: getMax(1,2,3);
0040D7C8 push 3
0040D7CA push 2
0040D7CC push 1
0040D7CE call ILT10(func) (0040100f)
0040D7D3 add esp,0Ch依次压入参数然后调用函数最后再堆栈外平衡重点在函数内部进去看看
函数内部
7: int getMax(int i,int j,int k){
0040D760 push ebp
0040D761 mov ebp,esp
0040D763 sub esp,40h
0040D766 push ebx
0040D767 push esi
0040D768 push edi
0040D769 lea edi,[ebp-40h]
0040D76C mov ecx,10h
0040D771 mov eax,0CCCCCCCCh
0040D776 rep stos dword ptr [edi]
8: if(ij){
0040D778 mov eax,dword ptr [ebp8]
0040D77B cmp eax,dword ptr [ebp0Ch]
0040D77E jle getMax32h (0040d792)
9: if(ik){
0040D780 mov ecx,dword ptr [ebp8]
0040D783 cmp ecx,dword ptr [ebp10h]
0040D786 jle getMax2Dh (0040d78d)
10: return i;
0040D788 mov eax,dword ptr [ebp8]
0040D78B jmp getMax42h (0040d7a2)
11: }else{
12: return k;
0040D78D mov eax,dword ptr [ebp10h]
0040D790 jmp getMax42h (0040d7a2)
13: }
14:
15: }else{
16: if(jk){
0040D792 mov edx,dword ptr [ebp0Ch]
0040D795 cmp edx,dword ptr [ebp10h]
0040D798 jle getMax3Fh (0040d79f)
17: return j;
0040D79A mov eax,dword ptr [ebp0Ch]
0040D79D jmp getMax42h (0040d7a2)
18: }else{
19: return k;
0040D79F mov eax,dword ptr [ebp10h]
20: }
21: }
22: }
0040D7A2 pop edi
0040D7A3 pop esi
0040D7A4 pop ebx
0040D7A5 mov esp,ebp
0040D7A7 pop ebp
0040D7A8 ret函数内部有不少代码是用来保护现场 初始化堆栈 恢复现场的这里将其过滤掉看判断语句
判断语句
8: if(ij){
0040D778 mov eax,dword ptr [ebp8]
0040D77B cmp eax,dword ptr [ebp0Ch]
0040D77E jle getMax32h (0040d792)
9: if(ik){
0040D780 mov ecx,dword ptr [ebp8]
0040D783 cmp ecx,dword ptr [ebp10h]
0040D786 jle getMax2Dh (0040d78d)
10: return i;
0040D788 mov eax,dword ptr [ebp8]
0040D78B jmp getMax42h (0040d7a2)
11: }else{
12: return k;
0040D78D mov eax,dword ptr [ebp10h]
0040D790 jmp getMax42h (0040d7a2)
13: }
14:
15: }else{
16: if(jk){
0040D792 mov edx,dword ptr [ebp0Ch]
0040D795 cmp edx,dword ptr [ebp10h]
0040D798 jle getMax3Fh (0040d79f)
17: return j;
0040D79A mov eax,dword ptr [ebp0Ch]
0040D79D jmp getMax42h (0040d7a2)
18: }else{
19: return k;
0040D79F mov eax,dword ptr [ebp10h]
20: }
21: }
22: }参数分析 ij
先来看看ij的反汇编语句
0040D778 mov eax,dword ptr [ebp8]
0040D77B cmp eax,dword ptr [ebp0Ch]
0040D77E jle getMax32h (0040d792)比较第一个参数和第二个参数
jlejump less equal小于等于则跳转有符号数
跳转地址0040d792
16: if(jk){
0040D792 mov edx,dword ptr [ebp0Ch]ik
9: if(ik){
0040D780 mov ecx,dword ptr [ebp8]
0040D783 cmp ecx,dword ptr [ebp10h]
0040D786 jle getMax2Dh (0040d78d)比较第一个和第三个参数
jlejump less equal小于等于则跳转有符号数
跳转地址0040d78d
11: }else{
12: return k;
0040D78D mov eax,dword ptr [ebp10h]
0040D790 jmp getMax42h (0040d7a2)可以分析出如果第一个参数小于等于第三个参数则跳转到0040D78D并将第三个参数赋值给eax作为返回值这条线路为(kij)
否则执行返回指令将第一个参数赋给eax作为返回值这条线路为(ij且ik)
10: return i;
0040D788 mov eax,dword ptr [ebp8]
0040D78B jmp getMax42h (0040d7a2)jk
16: if(jk){
0040D792 mov edx,dword ptr [ebp0Ch]
0040D795 cmp edx,dword ptr [ebp10h]
0040D798 jle getMax3Fh (0040d79f)比较第二个和第三个参数
jlejump less equal小于等于则跳转有符号数
跳转地址0040d79f
18: }else{
19: return k;
0040D79F mov eax,dword ptr [ebp10h]可以分析出如果第二个参数小于等于第三个参数则跳转到0040D79F并将第三个参数赋值给eax作为返回值这条线路为(ijk
否则返回执行返回命令将第二个参数赋值给eax作为返回值这条线路为(ij且kj)
17: return j;
0040D79A mov eax,dword ptr [ebp0Ch]
0040D79D jmp getMax42h (0040d7a2)总结
不难发现三个数求最大值只需两两比较就可以得出结果
分析if else的关键在于观察涉及的参数和jcc语句
此案例中就是直接采取了cmp 外加 jle来进行分支的选择和跳转
因为不符合条件的才要跳转走所以在条件比较中是大于的比较如ij所使用的汇编为jle 小于等于的比较
不按套路比较
此次案例并不能代表所有情况实际分析要具体看情况来采取分析有的程序可能就是不按套路出牌先看看按套路出牌的程序然后我们自己来模拟个不按套路的
正常套路
拿两个数的比较为例
#include stdafx.h
int getMax2(int i,int j){if(ij){return i;}else{return j;}
}
int main(int argc, char* argv[])
{getMax2(1,2);return 0;
}先看一般的汇编代码
9: if(ij){
0040D778 mov eax,dword ptr [ebp8]
0040D77B cmp eax,dword ptr [ebp0Ch]
0040D77E jle getMax225h (0040d785)
10: return i;
0040D780 mov eax,dword ptr [ebp8]
0040D783 jmp getMax228h (0040d788)
11: }else{
12: return j;
0040D785 mov eax,dword ptr [ebp0Ch]
13: }
14: }依旧是采用cmp 和 jle来进行判断和套路一致
不按套路
完整代码
#include stdafx.h
int __declspec(naked) myGetMax(int i,int j){__asm{ //保留调用前堆栈push ebp//提升堆栈mov ebp,espsub esp,0x40//保护现场push ebxpush esipush edi//初始化提升的堆栈填充缓冲区mov eax,0xCCCCCCCCmov ecx,0x10lea edi,dword ptr ds:[ebp-0x40]rep stosd//函数核心功能//取出参数mov eax,dword ptr ds:[ebp8]//比较参数cmp eax,[ebp0xC]jge _retmov eax,[ebp0xC]
_ret://恢复现场pop edipop esipop ebx//降低堆栈mov esp,ebppop ebp //返回ret }
}
int main(int argc, char* argv[])
{int resultmyGetMax(1,2);printf(%d\n,result);resultmyGetMax(4,3);printf(%d\n,result);return 0;
}功能代码分析
这里截取出我们自己实现比较的那段代码 //函数核心功能//取出参数mov eax,dword ptr ds:[ebp8]//比较参数cmp eax,[ebp0xC]jge _retmov eax,[ebp0xC]
_ret://恢复现场pop edipop esipop ebx//降低堆栈mov esp,ebppop ebp //返回ret 首先我们这里将第一个参数赋值给eax
然后比较eax和第二个参数也就是比较第一个参数和第二个参数
这边使用的就不是jle而是jge了
jgejump greater equal即大于等于则跳转
前面已经将第一个参数赋值给了eax而eax又是作为返回值来传递的
当第一个参数大于等于第二个参数时就可以直接返回了
如果不是则不跳转执行下面的将第二个参数赋值给eax作为返回值
这里注意到我在汇编中自己定义了一个段_ret来作为跳转的地址来使用
最后测试一下结果 可以正确得到两个数中的最大值