gpt4 book ai didi

c++ - 嵌入式 asm 代码中的运行时检查失败 #0

转载 作者:行者123 更新时间:2023-11-30 04:34:34 27 4
gpt4 key购买 nike

我对汇编程序有点陌生,但我正在尝试使用嵌入式汇编程序代码从 esp 堆栈中的 C++ 方法中查找参数。到目前为止,我什至无法将 esp 指针复制到 ebp 以便我可以保留堆栈(以防它发生变化)。即使是这一小段代码也让我失败了:

#include <stdlib.h>

int main(int argc, char* argv[])
{
__asm
{
mov ebp, esp
}
system("pause");
return 0;
}

运行后,我得到:

Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.

不知道该怎么办。请帮助我,在此先感谢。

最佳答案

通常,在将 ESP 的值移入 EBP 之前,您应该将 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++ 操作系统应用程序二进制接口(interface)上,EAX 保存函数的返回值,而不是 EBP.

还有一件事……如果您想要调用 get_stack_addr() 的实际函数的堆栈参数开始,则更改 movl %%ebp, %0\n\tmovl (%%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/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com