1

我正在编写一个 Windows 32 位程序,它在内联汇编中有一些部分。该程序旨在在 32 位和 64 位系统中运行。我正在为这两个系统编译一个 32 位版本。

我的问题是我假设堆栈宽度为 4 个字节宽。当我的 32 位程序在 64 Windows 系统下运行时,堆栈宽度仍然是 4 字节宽吗?

在我的程序中(这是简化版本)我在堆栈上推送一些值:

for (i=0;i<4;i++)   
    {
    _asm 
        {
        mov ebx,i   ; push 0,1,2,3 on the stack
        push ebx
        }
    }

稍后我将使用如下代码查询这些值:

ii=0;
for (i=0;i<5;i++)   
    {
    _asm 
        {
        mov ebx,ii   ; ii has 0, then 4, then 8 ...
        mov eax,dword ptr [esp+ebx]     ; peek values on the stack from the top
        mov num1,eax
        }
   ii+=4;   // here I am assuming stack width is 4 bytes  
   // -- do something with num1 --//
    }
4

2 回答 2

1

假设 64 位系统提供了一种向后兼容 32 位二进制文​​件的机制,那么堆栈仍然是 32 位宽的。

Windows x64 系统就是其中之一。

于 2012-10-23T18:20:26.750 回答
1

无论如何,堆栈实际上并没有“宽度”。它只是字节。有时期望堆栈指针对齐,但堆栈本身只是字节。您可以以任何您想要的方式使用该空间。您可以rSP手动操作并随心所欲地将其错位(这可能会导致麻烦,但您仍然可以)。您可以在任何偏移量处直接从堆栈读取/写入堆栈 - 甚至超出堆栈指针。

本质上,没有规则,只有系统其余部分的假设。如果您的代码未能满足这些假设,事情可能会出错,但没有什么可以阻止您从堆栈指针中减去 3,然后在您刚刚创建的空间中写入 5 个字节(显然它们不会全部适合)。

但是您实际上似乎要问的是:是否push r32在兼容模式下推送 dword?

是的,它确实。事实上,它总是在任何情况下都会这样做,否则它将无法组装。您不能编写push r32和“意外”推送一个 qword -push r32对于 64 位模式根本无法编码。

该行为不依赖于操作系统。

此外,您仍然可以在普通 32 位模式、兼容模式和 64 位模式下推送和弹出单词。而且,就像我之前说的,你可以继续使用堆栈指针做任何事情。

于 2012-10-23T18:38:19.407 回答