这并不容易。您必须知道调用者有多少个参数和局部变量,在大多数情况下,以编程方式计算出来并非易事。如果您做出可能错误的假设,即编译器保留EBP为堆栈帧持有者并且从不更改它(如,这可能不适用于 -O3/2/1)
在被调用函数内部,您可以执行类似的操作
mov ecx,ebp ;save our current stack frame
pop ebp ;get the old value of EBP that was there before our function got called
mov dword [_caller_address],dword [ebp+4] ;this isn't actually a valid opcode. you figure it out.
mov ebp,ecx ;restore old state
push ebp
不过这是非常不安全的。对编译器的优化可能会破坏它。它仅适用于 x86-32,并且取决于操作系统和编译器,如果它遵循不同的调用标准,它可能无法正常工作。
它的工作方式是这样的:
C中的函数看起来像
_Sum:
push ebp ; create stack frame
mov ebp, esp
mov eax, [ebp+8] ; grab the first argument
mov ecx, [ebp+12] ; grab the second argument
add eax, ecx ; sum the arguments
pop ebp ; restore the base pointer
ret
所以,如果说你有 _SumCall 它看起来像
_SumCall:
push ebp ; create stack frame
mov ebp, esp
mov eax, [ebp+8] ; grab the first argument
mov ecx, [ebp+12] ; grab the second argument
push ecx ;first argument for call
push eax ;second argument for call
call _Sum
pop ebp ; restore the base pointer
ret
所以你看,它依赖于被调用者负责堆栈帧保存的事实。
如果您尝试它但它不起作用,请确保调用者和被调用者至少有 1 个局部变量/参数。如果做不到这一点,那么你就搞砸了,因为编译器做了一些优化,打破了这个假设。
再次。这是非常不安全的并且非常不便携
参考:http ://courses.ece.illinois.edu/ece390/books/labmanual/c-prog-mixing.html