完美转发 - 组装

时间:2010-11-24 19:09:30

标签: assembly x86

如何在汇编中编写一个函数,只是将它的参数转发给另一个函数并添加一些额外的函数?

到目前为止,我推动了两个额外的参数,然后只是jmped到另一个函数。这有效吗?假设我使它成为一个裸体功能,没有prolog / epilog。我在x86。

1 个答案:

答案 0 :(得分: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位指令执行此操作。只需将ax更改为eax等。)

此外,这非常重要:只有在被调用者需要清理堆栈时才能使用。如果调用者需要清理堆栈(通常通过pop或通过添加到堆栈指针),那么这种技术将失败,因为调用者将在实际存在时从堆栈中删除2个参数4.结果将是一个损坏的堆栈帧,当调用者尝试执行ret指令时,它将徘徊于杂草中。