这篇文字解释这个问题:C语言函数调用在汇编语言是怎么实现的?栈模型很好的满足了函数调用的需求,以最简单的函数调用说明。
1 5: int add2(int a, int b){return a+b;} 2 0040B450 push ebp 3 0040B451 mov ebp,esp 4 0040B453 sub esp,40h 5 0040B456 push ebx 6 0040B457 push esi 7 0040B458 push edi 8 0040B459 lea edi,[ebp-40h] 9 0040B45C mov ecx,10h 10 0040B461 mov eax,0CCCCCCCCh 11 0040B466 rep stos dword ptr [edi] 12 0040B468 mov eax,dword ptr [ebp+8] 13 0040B46B add eax,dword ptr [ebp+0Ch] 14 0040B46E pop edi 15 0040B46F pop esi 16 0040B470 pop ebx 17 0040B471 mov esp,ebp 18 0040B473 pop ebp 19 0040B474 ret 20 21 --- No source file --------------------------------------------------------------------------------------------------------------------------------------- 22 0040B76C int 3 23 0040B76D int 3 24 0040B76E int 3 25 0040B76F int 3 26 --- e:项目 00test estconsolemain.cpp ----------------------------------------------------------------------------------------------------------------- 27 6: 28 7: int main(int argc, char **argv){ 29 0040B770 push ebp 30 0040B771 mov ebp,esp 31 0040B773 sub esp,4Ch 32 0040B776 push ebx 33 0040B777 push esi 34 0040B778 push edi 35 0040B779 lea edi,[ebp-4Ch] 36 0040B77C mov ecx,13h 37 0040B781 mov eax,0CCCCCCCCh 38 0040B786 rep stos dword ptr [edi] 39 8: 40 9: int a = 10; 41 0040B788 mov dword ptr [ebp-4],0Ah 42 10: int b = 20; 43 0040B78F mov dword ptr [ebp-8],14h 44 11: int c = add2(a, b); 45 0040B796 mov eax,dword ptr [ebp-8] 46 0040B799 push eax 47 0040B79A mov ecx,dword ptr [ebp-4] 48 0040B79D push ecx 49 0040B79E call @ILT+5(add2) (0040100a) 50 0040B7A3 add esp,8 51 0040B7A6 mov dword ptr [ebp-0Ch],eax 52 12: 53 13: return c; 54 0040B7A9 mov eax,dword ptr [ebp-0Ch] 55 14: } 56 0040B7AC pop edi 57 0040B7AD pop esi 58 0040B7AE pop ebx 59 0040B7AF add esp,4Ch 60 0040B7B2 cmp ebp,esp 61 0040B7B4 call __chkesp (0040b6b0) 62 0040B7B9 mov esp,ebp 63 0040B7BB pop ebp 64 0040B7BC ret
44行执行函数调用,过程如下:
(1)参数入栈,从右向左;
(2)CALL指令,注意CALL指令将EIP入栈,并JMP;
(3)初始化ADD函数堆栈,push ebp; mov ebp, esp;sub esp,0x40; push ebx; push esi; push edi; rep stos ptr dword es:[edi]. rep指令表示,执行循环,循环次数放置在ECX寄存器中;stos指令表示,将EAX值放入edi指向的地址,并将edi递增. 在第10行我们看到EAX被设置为0xCCCCCCCC,所以rep stos ptr dword es:[edi]的作用是,将开辟的0x40局部变量空间初始化为0xCC,0xCC是INT 3的汇编指令,目的是防止误执行。
(4)执行ADD指令,结果存放在EAX中;
(5)恢复现场,pop ebx; pop esi; pop edi;
(6)ret,弹出eip;
(7)保持栈平衡,add esp,8;