2010-11-24 41 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