首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

從反匯編學 C++(一):參數傳遞——常量入棧全過程圖解

     編輯:關於C語言

系列初衷

通過逆向工程視角,還原 C++ 高級語言特性在機器碼層面的真實樣貌,幫助開發者建立「代碼↔指令」的雙向映射心智模型。

實驗代碼

void testInt(int i) { i = 10; }
int main() { testInt(1); return 0; }

主調函數 main 反匯編分析

00A813CE  push 1           ; 立即數 1 入棧(4 字節)
00A813D0  call testInt     ; 壓入返回地址,跳轉 testInt
00A813D5  add esp, 4       ; 清理參數棧空間(呼叫者清理,__cdecl 約定)
  • push 1:將常量 1 壓入棧頂,ESP -= 4
  • call:壓入下一條指令地址 (00A813D5) 作為返回地址,EIP = testInt
  • add esp, 4:呼叫者負責棧平衡,彈出參數

被調函數 testInt 反匯編分析

009B1380  push ebp                ; 保存舊幀指針
009B1381  mov  ebp, esp           ; 建立新幀:EBP = ESP
009B1383  sub  esp, 0C0h          ; 分配局部變量空間(編譯器調試填充)
009B1389  push ebx                ; 保存被調用者保存寄存器
009B138A  push esi
009B138B  push edi
009B138C  lea  edi, [ebp-0C0h]    ; 以 0xCCCCCCCC 填充棧(調試模式)
009B1392  mov  ecx, 30h
009B1397  mov  eax, 0CCCCCCCCh
009B139C  rep  stos dword ptr es:[edi]
009B139E  mov  dword ptr [ebp+8], 0Ah  ; ★ 核心語句:i = 10
009B13A5  pop  edi                ; 恢復寄存器
009B13A6  pop  esi
009B13A7  pop  ebx
009B13A8  mov  esp, ebp           ; 撤銷幀
009B13AA  pop  ebp
009B13AB  ret                     ; 彈出返回地址到 EIP

關鍵洞見:參數在棧上的位置

執行至 mov ebp, esp 後,棧佈局如下:

高地址
+----------------+
|  返回地址      |  <-- EBP+4
+----------------+
|  參數 1 (值 1) |  <-- EBP+8  ★
+----------------+
|  舊 EBP        |  <-- EBP
+----------------+
|  局部變量區    |  <-- ESP
低地址
  • EBP+8 固定指向第一個參數(32 位 __cdecl 約定)
  • mov dword ptr [ebp+8], 0Ah 直接修改棧上參數副本,**不影響調用者實參**(常量無地址,即便是變量也是值傳遞副本)

調用返回後的棧清理

ret 彈出返回地址 → EIP = 00A813D5 → add esp, 4 釋放參數空間 → 棧完全平衡。

總結

  1. 常量參數:直接 push 立即數 入棧
  2. 調用約定 __cdecl:參數右至左入棧,呼叫者清理棧
  3. 幀指針 EBP 為基準,[EBP+8] 訪問第一參數,[EBP+12] 訪問第二參數...
  4. 函數序言/結語(保存/恢復 EBP、EBX、ESI、EDI、分配/釋放局部空間)為編譯器自動生成

下一期將分析變量參數傳遞與引用/指針參數的棧幀差異。

本文轉載自 “三人乘虎” 博客,原文地址:https://darhx.blog.51cto.com/7920146/1304242

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved