16

我了解到您不能将字节直接推送到英特尔奔腾的堆栈中,有人可以向我解释一下吗?

我得到的原因是因为 esp 寄存器是字可寻址的(或者,这是我们模型中的假设)并且它必须是“偶数地址”。我会假设递减一些 32 位二进制数的值不会弄乱寄存器的对齐方式,但显然我还不够了解。

我已经尝试了一些 NASM 测试并提出如果我声明一个变量(bite db 123)并将其推送到堆栈中,esp 会减少 4(表明它推送了 32 位?)。但是,“push byte bit”(对不起,我选择了变量名)会导致一个错误:

test.asm:10:错误:不支持的非 32 位 ELF 重定位

在这个困难时期,任何智慧之言都将不胜感激。我是一年级本科生,很抱歉我在这方面的天真。

4

4 回答 4

13

在某些情况下,它会使堆栈指针无法完成其工作。例如,假设您有一个函数将一个字节压入堆栈,然后调用另一个函数。该调用最终会尝试将未对齐的返回地址写入堆栈,从而导致错误。

于 2010-04-06T16:45:55.293 回答
6

它基于堆栈的创建方式:

堆栈段的地址大小属性决定堆栈指针大小(16、32 或 64 位)。当前代码段的操作数大小属性决定了堆栈指针的递减量(2、4 或 8 个字节)。

在非 64 位模式下:如果地址大小和操作数大小属性为 32,则 32 位 ESP 寄存器(堆栈指针)减 4。如果两个属性均为 16,则 16 位 SP 寄存器(堆栈指针)减 2。

资料来源: http: //www.intel.com/Assets/PDF/manual/253667.pdf

pg。4-320 卷。2B

编辑

只是想指出一个有趣的阅读是手册中关于堆栈的部分,它将进一步解释创建堆栈段。

http://www.intel.com/Assets/PDF/manual/253665.pdf

第 6.2 章

于 2010-04-06T16:50:00.203 回答
1

您要做的是使用位旋转操作码在每个 32 位内存位置循环,一次将 8 位放入寄存器,直到您旋转回起始位位置。现在您的 32 位寄存器中应该有 4 个 8 位数量并排排列。现在将其压入堆栈,您就完成了。

于 2010-04-06T16:49:45.733 回答
0

堆栈指针必须(出于某些优化原因)4B 对齐 -> 它应该可以被 4 整除(因此,最后 2 位为零)。

于 2010-04-06T16:44:36.530 回答