在单独分配的堆栈上运行函数

时间:2012-08-03 05:50:00

标签: c++ assembly x86 stack

我正在尝试在单独分配的堆栈上运行一个函数。

我想稍后保留堆栈,以便我可以恢复它并恢复该功能。

以下代码编译并运行,但没有任何内容打印到屏幕上。

#include <cstdlib>
#include <csetjmp>
#include <iostream>
using namespace std;

unsigned char stack[65535];
unsigned char *base_ptr = stack + 65535 - 1;

unsigned char *old_stack;
unsigned char *old_base;

void function()
{
    cout << "hello world" << endl;
}

int main()
{
    __asm
    {
        mov old_base, ebp
        mov old_stack, esp

        mov ebp, base_ptr
        mov esp, base_ptr

        call function

        mov ebp, old_base
        mov esp, old_stack
    }
}

使用vs2012 / win8 / intel Q9650

3 个答案:

答案 0 :(得分:2)

欢迎使用C ++并命名mangling。 C ++中的函数名被编译器破坏(因此使用gcc函数对我来说变成了_Z8functionv)。这是为了方便功能重载。编译器会跟踪它在后台提供不同功能的实际名称,因此您不会意识到它。对于尝试与C ++交互的任何其他语言,这都是一个问题。

此代码不会在我的计算机上链接。

解决方案: 1)用g ++编译并传递-S标志(所以g ++ -S test.cpp)。然后看一下程序集输出(cat test.s)以查看函数的调用内容。然后将“调用函数”中的名称更改为“调用_Z8functionv”(对我来说 - 它可能很容易与您不同)。 2)使用C:改变cout&lt;&lt;对于printf语句,以上内容应该有效。

我认为你没有使用gcc(因为汇编程序回到了前面,因为我不得不切换汇编程序上的所有操作数)。

答案 1 :(得分:1)

根据英特尔针对MOV的x86文档(第3-403页),您应该在加载新SS值之前立即加载ESP寄存器。这会阻止任何中断运行,直到ESP被分配。

答案 2 :(得分:1)

实际上我没有看到您的代码有任何问题。 您的样本按原样进行编译,链接和运行。

也许您的控制台设置问题,或某些全局STL / CRT初始化或其他问题。无论如何,你可以在function内放一个断点,以确保你到达那里。