一段C代码:
int _tmain(int argc, _TCHAR* argv[])
{
return 0;
}
编译后汇编代码:
mainret = wmain(argc, argv, envp);
013C16C6 mov eax,dword ptr [envp (13C7140h)]
013C16CB push eax
013C16CC mov ecx,dword ptr [argv (13C7144h)]
013C16D2 push ecx
013C16D3 mov edx,dword ptr [argc (13C713Ch)]
013C16D9 push edx
013C16DA call @ILT+5(_wmain) (13C100Ah) //调用main函数
013C16DF add esp,0Ch //main函数ret指令后执行
013C16E2 mov dword ptr [mainret (13C7154h)],eax
int _tmain(int argc, _TCHAR* argv[])
{
013C1350 push ebp
013C1351 mov ebp,esp
013C1353 sub esp,0C0h
013C1359 push ebx
013C135A push esi
013C135B push edi
013C135C lea edi,[ebp-0C0h]
013C1362 mov ecx,30h
013C1367 mov eax,0CCCCCCCCh
013C136C rep stos dword ptr es:[edi]
return 0;
013C136E xor eax,eax
}
013C1370 pop edi
013C1371 pop esi
013C1372 pop ebx
013C1373 mov esp,ebp
013C1375 pop ebp
013C1376 ret
函数调用前程序各种寄存器的值:
EAX = 00574290 EBX = 7EFDE000 ECX = 005731E0 EDX = 00000001 ESI = 00000000 EDI = 00000000 EIP = 013C1350ESP = 0037FD3C EBP = 0037FD88 EFL = 00000202
常见汇编指令:
- 堆栈指令:(堆栈从高向低地址增长)
Push:将一个32的操作数入栈,esp寄存器将被减4
Pop:相反,esp寄存器将被加4
Sub:减法,第一个参数被减去的寄存器,第二个参数减数
Add:加法
Ret:返回,返回到调用者Call指令的下一条指令
- 数据传送指令:
Mov:数据移动,第一个目的,第二个来源
Xor:异或,逻辑运算指令,xor eax eax指令常代替move exa 0指令,速度更快。
xor eax eax,看见这样的指令应该明白就是清零操作
Lea:将第二个参数的地址,放入前面寄存器中。
lea edi,[ebp-0C0h] //[]表示存储器,ebp-0C0h表示存储器内容
Rep:串存储指令,它的功能是将eax的值放入到edi所指的地址中,同时edi增加4字节。Ret指令重复ecx中填写的次数。
C函数的参数传递
1、_cdcel C调用规则:(C编译器的默认规则)
(1)参数从右到左依次入堆栈
(2)调用函数
(3)函数返回后,由被调用者清理堆栈(_stdcall由调用者清理堆栈)。
注:在Windows中,不管哪中调用方法,所有的返回值都放在eax中,然后返回。外部由eax得到返回值。
2、_cdcel函数调用汇编分析:
(1)保存ebp。ebp总是用于保存函数执行前的esp的值,函数执行完成后用ebp恢复esp的值。执行前将ebp值入栈,函数返回时弹出,恢复ebp值。
push ebp
mov ebp,esp
(2)在堆栈中预留一个区域用来保存局部变量。
sub esp,0C0h
(3)保存ebx,esi,edi到堆栈中,调用完恢复。
push ebx
push esi
push edi
(4)把局部变量区域全部初始化为0CCCCCCCCh。
lea edi,[ebp-0C0h]
mov ecx,30h
mov eax,0CCCCCCCCh
rep stos dword ptr es:[edi]
(5)edi、esi、ex出栈,恢复esp、ebp
return 0;
xor eax,eax
}
pop edi
pop esi
pop ebx
mov esp,ebp //恢复esp值:0037FD40
pop ebp //恢复ebp值:0037FD3C
ret
函数调用返回后的寄存器值
EAX = 00000000 EBX = 7EFDE000 ECX = 00000000 EDX = 00000001 ESI = 00000000 EDI = 00000000 EIP = 013C16DFESP = 0037FD40 EBP = 0037FD88 EFL = 00000246
esp值恢复,ebp值0037FD3C减4为0037FD40堆栈下个地址,一个函数调用远程完成。
汇编学习-汇编指令与C语言
最新推荐文章于 2023-04-08 19:33:00 发布