2012-08-03 59 views
0

我试图在单独分配的堆栈上运行函数。在单独分配的堆栈上运行函数

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

下面的代码编译并运行,但没有打印到屏幕上。

#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 /英特尔Q9650

+0

也许'setjmp' /'longjmp'可能对您的问题有用? – 2012-08-03 06:06:35

+0

setjmp/longjmp不保留堆栈,只有cpu注册。所以,如果你跳出一个函数,局部变量可以被覆盖。 – bitwise 2012-08-03 06:09:16

+1

你不会告诉我们你正在使用哪个编译器。有一个支持MASM风格的程序集,我会写'mov ebp,[base_ptr]'和'mov esp,[base_ptr]'。 – 2012-08-03 06:59:38

回答

1

其实我没有看到你的代码有任何问题。 您按照原样编译,链接并按预期运行。

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

+0

很奇怪........我只是将平台工具集从“Visual Studio 11(v110)”更改为“Visual Studio 2010(v100)”,现在工作=/ – bitwise 2012-08-03 07:23:19

+1

@albundy也许VS11不适合在64K的堆栈中。尝试a)增加堆栈大小; b)优化编译; c)使用printf而不是cout。 – 2012-08-03 12:25:29

+0

@Igor Skochinsky:正确的点(尽管显示字符串输出函数调用链不适合64K堆栈似乎很奇怪)。通常,堆栈顶部有一个不可访问的页面,因此其访问会导致堆栈溢出或访问冲突异常。而超过这个自定义的“堆栈”只会覆盖一些全局数据或类似的东西...... – valdo 2012-08-03 14:21:15

1

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

+2

这是为了同步,如果你要加载* SS和ESP。这里不会发生。 – 2012-08-03 06:56:18

+0

这不是我在阅读文档时得到的印象。我读过它说你必须在ESP之前设置SS,所以当ESP不处于稳定状态时,中断不能运行。设置SS阻止所有中断运行,直到下一条指令完成执行。 – 2012-08-03 19:20:43

+0

如果你想改变* SS和ESP,你的解释是正确的。原来的8086没有这个功能,所以在移动堆栈时存在竞争条件的风险。这里我们只用一条指令来改变ESP。那么就没有风险,因为中断只能发生在*指令之间,而不是在期间。 – 2012-08-03 19:30:57

2

欢迎使用C++和名称修饰。 C++中的函数名称被编译器破坏(例如,使用gcc函数变成_Z8functionv)。这是为了方便功能重载。编译器会跟踪它在后台赋予不同功能的实际名称,因此您不知道它。对于任何试图与C++交互的其他语言而言,这是一个问题。

此代码将不会链接到我的电脑上。

解决方案: 1)用g ++编译并传递-S标志(so g ++ -S test.cpp)。然后看看汇编输出(cat test.s)来查看函数的调用。然后将“call function”中的名称更改为“call _Z8functionv”(对于我来说 - 对于您来说可能很不一样)。 2)使用C:将cout < <更改为printf语句,并且上述内容应该可以工作。

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

+0

我在函数()中放置了一个断点,并且正在调用它。我甚至可以通过cout code =/ – bitwise 2012-08-03 06:49:50

+0

几乎你的代码:http://pastebin.com/JsFQSAsy,用g ++编译,并运行,打印出“Hello World”。你使用的是什么环境(编译器/操作系统/机器)? – dave 2012-08-03 06:52:57

+0

vs2012/win8/intel Q9650 – bitwise 2012-08-03 07:04:49