常見面試題「參數從左往右還是右往左壓棧?」答案是視架構而定:
| 架構 | 壓棧順序 | 驗證程式輸出 |
|---|---|---|
| 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 |
#includeint 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; }
push ebp mov ebp, esp ; 呼叫端: push 2 ; 參數 2 先入棧 push 1 ; 參數 1 後入棧 call test ; 被調用端: mov eax, [ebp+8] ; 參數 1 mov ebx, [ebp+12] ; 參數 2
; 呼叫端: 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 的視覺現象。
反組譯是理解呼叫慣例的唯一可靠來源。不要憑記憶或舊教材假設,始終以目標架構 ABI 文檔為準。