我对汇编程序有点陌生,但是我试图使用嵌入式汇编程序代码从esp
堆栈中的C++方法中查找参数。到目前为止,我什至无法将esp
指针复制到ebp
,因此我可以保留堆栈(以防更改)。即使这小段代码也给我带来了失败:
#include <stdlib.h>
int main(int argc, char* argv[])
{
__asm
{
mov ebp, esp
}
system("pause");
return 0;
}
运行此命令后,我得到:
不知道该怎么办。请帮助我,并预先感谢。
最佳答案
通常,在将EBP
的值移动到ESP
之前,应该将EBP
的当前值压入堆栈。 EBP
是32位平台上的“callee-save”寄存器,这意味着如果要在函数中对其进行修改,则必须先保存它。
如果您希望函数返回堆栈指向的位置(或函数调用后将返回的位置)的值,则最好的操作如下:
void* get_stack_addr()
{
void* stack_ptr = NULL;
//on 32-bit systems
//EBP is pointing at top of stack frame
//EBP + 4 is the return instruction address
//EBP + 8 is the value that was in ESP before function call for a function with no arguments
__asm__
(
"movl %%ebp, %0\n\t"
"addl $8, %0\n\t"
: "=r" (stack_ptr)
);
return stack_ptr;
}
这样,
EAX
现在保存调用get_stack_addr()
之前堆栈指向的值的地址。如果您只是在函数中返回了ESP
的值,则实际上您不知道要指向的位置,因为编译器通常会在C / C++函数中填充堆栈以保持适当的堆栈对齐。它还经常在堆栈上为所有局部变量保留空间,这将再次导致堆栈计算失败。通过使用指向堆栈框架顶部的EBP
,您可以在32位平台上准确地计算函数调用之前的堆栈值。最后,我们将返回值放在EAX
中,因为在大多数C / C++的OS应用程序二进制接口(interface)上,EAX
保留了函数的返回值,而不是EBP
。还有一件事情……如果您想为调用
get_stack_addr()
的实际函数在堆栈上启动参数,则将movl %%ebp, %0\n\t
更改为movl (%%ebp), %0)\n\t
。这样,您现在可以获取先前的堆栈框架基本指针(即调用方的堆栈框架基本指针),并通过向该地址添加+8值来获取存储的参数的开头在返回地址上方,或者您正在查看的地址指向指向当前函数的调用者的堆栈框架(即,先前的堆栈框架)。作为增强功能
"leal 8(%%ebp), %0\n\t"
可以替代:"movl %%ebp, %0\n\t"
"addl $8, %0\n\t"
该
leal
指令会将EBP的值加8,并将结果存储在输出操作数中。关于c++ - 嵌入式asm代码中的运行时检查失败#0,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/5902157/