在嵌入式汇编code运行时检查失败#0 [英] Run-Time Check Failure #0 in embedded asm code

查看:104
本文介绍了在嵌入式汇编code运行时检查失败#0的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

嗨伙计!我是一个有点新的汇编程序,但我试图查找从ESP堆栈中的C ++方法的参数,使用嵌入式汇编code。到目前为止,我还没有能够复制ESP指针EBP这样我就可以得到堆栈上的保持(的情况下,它的变化)。即使这样小片code的给我失败的原因:

Hey folks! I'm a bit new to assembler, but I'm trying to lookup the parameters from a C++ method in the esp stack, using embedded assembler code. So far I haven't even been able to copy the esp pointer to ebp so I can get a hold on the stack (in case it changes). Even this little piece of code gives me the failure:

#include <stdlib.h>


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

我跑在此之后,我得到:

After I run this, I get:

运行时检查失败#0 - ESP的值未正确保存跨函数调用。这通常是调用带有一个不同的调用约定声明的函数指针执行调用约定声明的函数的结果。

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.

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

Don't know what to do. Help me please, and thanks in advance.

推荐答案

一般来说,你应该推 EBP 的当前值在堆栈中移动前值 ESP EBP EBP 是被调用者保存在32位平台上注册,如果你要修改它在一个函数的意义,必须先保存它。

In general you should push the current value of EBP on the stack before you move the value of ESP into EBP. EBP is a "callee-save" register on 32-bit platforms, meaning if you are going to modify it in a function, you must save it first.

如果你想你的函数返回的值堆栈的指向(或在那里将函数调用返回后),待办事项,最好的办法是以下内容:

If you want your function to return the value of the where the stack is pointing (or where it will return after the function call), the best thing to-do would be the following:

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, %%eax\n\t"
                "addl $8, %%eax\n\t"
                : "=r" (stack_ptr)
        );

        return stack_ptr;
}

现在

这样 EAX 持有的价值堆栈指着调用 get_stack_addr()之前制成。如果你只是在函数返回 ESP 的价值,你居然不知道你在哪里指向,因为编译器常常垫堆在C / C ++函数为了保持正确的栈对齐。它也经常保留堆栈所有局部变量,这再次将甩开栈的计算上的空间。通过使用 EBP ,它指向堆栈帧的顶部,您可以准确地调用函数之前计算在32位平台上,堆的价值。最后,我们把在 EAX 的返回值,因为对C / C ++最OS应用程序二进制接口, EAX 保存了返回函数的值,而不是 EBP

That way EAX is now holding the address of the value that the stack was pointing to before the call to get_stack_addr() was made. If you just returned the value of ESP in the function, you actually have no idea where you're pointing to, since the compiler often pads the stack in a C/C++ function in order to maintain proper stack alignment. It also often reserves space on the stack for all local variables, which again will throw off the calculation of the stack. By using EBP, which points at the top of the stack frame, you can accurately calculate on a 32-bit platform, the value of the stack before the function call. Finally we place the return value in EAX since on most OS application binary interfaces for C/C++, EAX holds the return value of a function, not EBP.

一件事...如果你是在堆栈调用的实际功能上想要的参数启动 get_stack_addr(),然后更改 MOVL %% EBP,EAX %% \\ n \\ t MOVL(EBP %%),EAX %%)\\ n \\ t 。这样,现在你得到了previous栈帧基址指针(即主叫方的堆栈帧基指针),并通过添加+8值到该地址,你得到的要么开始参数存储在返回地址上面,或者你正在寻找一个地址指向到当前函数的调用者(即previous堆栈帧)。

One more thing ... if you are wanting start of the parameters on the stack for the actual function that calls get_stack_addr(), then change movl %%ebp, %%eax\n\t to movl (%%ebp), %%eax)\n\t. That way you're now getting the previous stack-frame base pointer (i.e., the stack frame base pointer of the caller), and by adding a value of +8 to that address, you're getting either the beginning of the parameters stored above the return address, or you're looking at an address pointing into the stack frame for the caller of the current function (i.e., the previous stack frame).

这篇关于在嵌入式汇编code运行时检查失败#0的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆