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

C 語言函數調用參數壓棧順序與 32/64 位架構差異深度解析

     編輯:關於C

參數入棧順序:架構相關

常見面試題「參數從左往右還是右往左壓棧?」答案是視架構而定:

架構壓棧順序驗證程式輸出
32 位 x86 (cdecl)右到左address of a > address of b → 參數 b 先入棧(地址較高)
64 位 x86-64 (System V AMD64 ABI)左到右(視覺上)前 6 個整數/指標參數經寄存器 RDI, RSI, RDX, RCX, R8, R9 傳遞,被調用者序言代碼按順序存入棧框,導致 &a < &b

驗證程式碼

#include 
int test(int a, int b) {
    printf("address of a %p\n", (void*)&a);
    printf("address of b %p\n", (void*)&b);
    if ((uintptr_t)&a > (uintptr_t)&b)
        puts("Push argument from left to right...");
    else
        puts("Push argument from right to left...");
    return 0;
}
int main() { test(1, 2); return 0; }

棧框佈局對比

32 位:參數直接入棧

push ebp
mov  ebp, esp
; 呼叫端:
push 2      ; 參數 2 先入棧
push 1      ; 參數 1 後入棧
call test
; 被調用端:
mov eax, [ebp+8]   ; 參數 1
mov ebx, [ebp+12]  ; 參數 2

64 位:寄存器傳參 + 棧框存儲

; 呼叫端:
mov edi, 1      ; 參數 1 -> RDI
mov esi, 2      ; 參數 2 -> RSI
call test
; 被調用端序言:
push rbp
mov  rbp, rsp
mov  [rbp-4], edi   ; 參數 1 存入棧框較高地址
mov  [rbp-8], esi   ; 參數 2 存入棧框較低地址

因寄存器傳參順序固定(左到右對應 RDI, RSI...),序言代碼依序存入棧框,造成 &a < &b 的視覺現象。

核心差異總結

  1. 32 位:所有參數直接壓棧,右到左,呼叫端負責清理棧(cdecl)。
  2. 64 位:前 6 整數/指標參數用寄存器,超出部分才壓棧(右到左);浮點參數用 XMM0-7;被調用端序言將寄存器參數存入棧框(Home space),形成左到右的地址遞增假象。

反組譯是理解呼叫慣例的唯一可靠來源。不要憑記憶或舊教材假設,始終以目標架構 ABI 文檔為準。

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