棧幀
每一次函數調用都有一個過程,稱為“函數調用過程”,這個過程要為函數開辟棧空間,用于本次函數的調用中臨時變量的儲存,現場保護。這個棧空間稱為函數的調用過程。
Ⅰ.寄存器
基址寄存器(棧底寄存器):EBP
棧頂寄存器:ESP
通用寄存器:EAX,EDX,EBX,ECX.
Ⅱ.彙編指令:
call:功能:1.将目前正在執行指令的下一條指令的位址壓人棧中;2.随即call會跳轉至指定函數(jmp)
ret(傳回):1.彈出(pop)棧頂;2.彈出後的棧頂元素放入EIP。
Ⅲ.研究代碼
#include<stdio.h>
#include<windows.h>
int myadd(int x,int y)
{
int z = x + y;
return z;
}
int main()
{
int a = 0xAAAAAAAA;
int b = 0xBBBBBBBB;
int c = 0;
c = myadd(a,b);
printf("you should run here\n");
printf("result:%d\n",c);
system("pause");
return 0;
}
Ⅳ.棧幀過程:
1.main函數中的棧幀以及main函數調用時形參的執行個體化:

2.傳回把目前執行指令的下一條指令儲存,esp中a的位址比b小:
3.由反彙編得call指令的下一條指令的位址為0040109A,将它壓入棧中,F11後下圖中0019FEDC變為0040109A(小端)
通過jmp到指定函數myadd處 寄存器EIP變為00401020
在myadd函數中:
再把EBP mov 給esp得
mov前為:
mov後為:
此時ebp指向esp
下一條指令00401023為給ESP-4,是以此時ESP要往下移,形成了一個新的空間,這個空間為myadd的棧幀。
上面3條指令所表達的意思:
1.把ebp+8(a) mov 給eax;
2.把 ebp+12(b) 與eax相加為eax;
3.eax mov給 ebp-4,是以此時棧幀如下:
函數調用完成之後
把ESP mov 給ebp,彈出(pop)棧頂給ebp,是以此時的ebp為main函數的ebp,下一步傳回ret,ret作用為彈出(pop)棧頂并把彈出後的棧頂值放入EIP。此時恢複到main函數的棧幀内,如下:
最後如下:
謝謝觀看。