2010-11-24 38 views
1

如何在彙編中編寫一個函數,將函數的參數轉發給另一個函數並添加一些額外的函數?完美轉發 - 在彙編中

到目前爲止,我推出了兩個額外的參數,然後只是jmped到另一個函數。這有效嗎?假設我使它成爲一個裸體功能,沒有序言/ epilog。我在x86中。

+0

如果你只是跳到其他函數的返回地址呢? – 2010-11-24 19:23:33

回答

4

如果你想做到這一點,你需要彈出返回地址,推入你的兩個參數,將返回地址推回棧中,然後跳轉。

下面的討論假設你在一個不保留我修改的寄存器的環境中這樣做,並且你正在使用一個純粹的基於棧的調用約定。如果有保留的寄存器(例如,如果你正在編寫一個由C程序調用的ASM函數)或者調用約定是基於寄存器的,那麼事情就會有所不同。

此外,請務必在最後閱讀聲明。

有了這樣的方式......

想象一下,你有這就是所謂的棧上兩個參數的功能。堆棧幀,在進入你的函數,應該是這樣的:

arg1 
arg2 
return addr 

讓我們不要狡辯參數排序(即cdecl VS stdcall)。

現在,您想要將控制權傳遞給期望這兩個參數和另外兩個參數的另一個函數。在進入該功能,棧幀應該是這樣的:

arg1 
arg2 
arg3 
arg4 
return addr 

所以,你的第一個功能具有流行的返回地址,添加兩個新的參數,按下返回地址,並做跳躍:

passthrough: 
    ; save the return address 
    pop ax 
    ; Do stuff here to load values in BX and CX 
    ; now push BX and CX (other parameters) 
    push bx 
    push cx 
    ; restore the return address 
    push ax 
    ; Branch to the new function. 
    ; The new function's RETurn will return to the caller of this function 
    jmp new_function 

(是的,我這樣做,與16位指令,只要改變axeax,等等。)

而且,這是非常重要的:這隻能如果被叫預計將清理堆棧。如果調用者希望清理堆棧(通常是通過添加或添加堆棧指針),則此技術將失敗,因爲調用者期望在實際存在4時從堆棧中移除2個參數。結果將是一個損壞的堆棧幀,當調用者試圖執行ret指令時,它將會漫遊到雜草中。

+0

x86需要調用者清理(通常在調用後你會看到'add%esp`,儘管聰明的編譯器有時會批量調用這些)。您只能使用相同數量或更少的參數進行尾部呼叫。 – 2010-11-24 20:49:17