2013-11-20 52 views
6

的論點我有簽名的函數:檢索64 MASM裝配過程

extern "C" int foo(int a, int b, int c, int d, int e); 

這實際上是彙編語言編寫的。

隨着毫升(32位),使用標準調用約定你幾乎可以寫

.code 
foo PROC a: DWORD, b: DWORD ,c: DWORD, d: DWORD, e: DWORD 

    mov eax, d 
    mov ebx, e 

,並開始使用這些標籤來訪問你的論點

隨着ml64(64位)的快速調用是隻有約定可用。我沒有問題訪問存儲在寄存器中的第一個論據,但問題來訪問那些在堆棧(e在這個例子中):我想

.code 
foo PROC a: DWORD, b: DWORD ,c: DWORD, d: DWORD, e: DWORD 

.code 
foo PROC e: DWORD 

但在價值e是垃圾。

我發現如果直接使用堆棧地址,我會找到該值。

.code 
foo PROC e: DWORD 

    mov eax, r9     ; d 
    mov ebx, DWORD PTR[rbp + 48] ; e 

有另一種方式?

回答

3

文檔說明了一切......在Windows中,前四個整數參數在寄存器RCXRDXR8R9XMM0浮點,XMM1XMM2XMM3,任何超過四個參數傳遞傳遞陰影空間之上的堆棧。對於Unix類型的操作系統,它有點不同。

所以,你的例子是正確的 - mov ebx, DWORD PTR[rbp + 48] ; e

暗影空間= 32 +保存RBP = 40 + 5參數= 48

0

給出

extern "C" int foo(int a, int b, int c, int d, int e); 

我發現,Visual Studio 2010中沒有按「T保存的基指針RBP如果

.code 
foo PROC 

但保存基本指針,如果

.code 
foo PROC e: DWORD 

以後的版本(vs2015)不允許第二個代碼。

There is an optional optimization in x64 systems where RBP is not used(發現困難的方式)。它說:

常規使用%RBP的作爲堆棧幀 幀指針可以通過使用%RSP(堆棧指針)索引到 堆棧幀被避免。該技術在序言和尾聲中保存了兩條指令,並且還提供了一個額外的通用寄存器(%rbp) 。

所以有可能foo PROC e: DWORD不會編譯(vs2015)或foo PROC崩潰,因爲RBP爲空。

檢索棧參數的正確方法是使用給出的RSP棧指針

num_saved_reg是在PROC指令指定的寄存器的數目。所以當rbp沒有保存(否則加8)

PROC -> DWORD PTR[rsp + 40] 
PROC use RDI -> DWORD PTR[rsp + 40 + 8] 
PROC use RDI RSI RBX -> DWORD PTR[rsp + 40 + 24]