C++程式碼反彙編後的函式呼叫過程,堆疊暫存器EBP和ESP
阿新 • • 發佈:2019-02-20
棧是從高地址向低地址生長的。 ebp始終指向當前棧幀的棧底部 , 通過ebp+4中儲存著函式的返回地址 。函式返回時將EBP的值推給EIP ,返回到上一個函幀繼續執行。
ret 與call指令 相反 ,call 將EIP壓入堆疊,然後跳到標號處。
ret 8 在函式返回後將ESP+8 ,平衡棧幀(由被呼叫者平衡棧幀--C呼叫約定) 。 (stdcall由呼叫者平衡棧幀,引數壓入順序也從右向左)
ebp+8儲存著引數1 , ebp+0c 引數2 ,類似....。 前提是使用C(或者stdcall)呼叫約定,引數從右向左開始壓入棧。
每一個函式呼叫的反彙編開始執行前都有
push ebp
mov ebp,esp
sub esp ,0ch ;棧子空間, 這句的前提是函式有區域性引數 ,開闢的大小也根據編譯器不同而各異,當然肯定大於區域性變數的引數
函式結束後都有以下兩句
mov esp , ebp ;不管前面esp開闢了多少棧空間,通過一個ebp賦值,就全回收了。
pop ebp ; 還原前棧幀的EBP, //此時ESP = ESP-4 , ESP指向了返回地址
ret ; 即將ESP(其實都是從EBP恢復出來的)儲存的返回地址彈給EIP,返回到呼叫前的地址, , C呼叫還需要平衡棧幀ret 8;(假如兩個引數)
棧是從高地址向低地址生長的。每開闢一個棧幀肯定是在前棧幀的低地址位置。
盜個圖