1

在一些教程中,据说堆栈指针指向堆栈的顶部元素:

+-------------+
|    stack    |
+-------------+
| top element |  <-- esp
+-------------+

在其他情况下,据说它指向它的右侧,因此指向当堆栈增长时可以写入的第一个内存地址。

+-------------+
|    stack    |
+-------------+
| top element | 
+-------------+  <-- esp

在这个德国维基百科网站 https://de.wikipedia.org/wiki/Register_(Computer)#Stapelregister 上,据说这两个版本都存在并且它取决于 CPU 架构。

我的问题是,它在 x86-CPU 上怎么样?它还取决于操作系统吗?

4

1 回答 1

4

假设您处于 32b x86 模式,并且您将地址 100 到 200 的内存保留为堆栈(虚幻,太低,会与 IVT 冲突,但在此示例中可以)。堆栈中已经有一些值,esp160 也是。

现在“栈顶值”在地址 160、161、162 和 163(四个字节,因为在 32b 模式下,栈中的单个值是 32b = 4B 大)占用内存,假设有存储值0xaabbccdd

如果你现在这样做push 0x12345678,CPU 将首先从esp-> new中减去 4 esp = 156; (160-4)。然后它将写入 32b 值,以 little-endian 方式分解为四个字节:mem[156] = 0x78, mem[157] = 0x56, mem[158] = 0x34, mem[159] = 0x12.

现在如果你执行mov eax,[esp],它将从地址 156 加载 32 位值,这意味着它将从地址 156、157、158、159 处的四个字节组成 32b 值到dword值 0x12345678。

最后,当您在推送后在调试器中查看内存时,从ss:esp地址查看它,它将包含这些字节(十六进制):

0000009C:  78 56 34 12 DD CC BB AA ....

(0x9C = 156 = 内存视图开始的地址)。值的第一个字节处的esp点,被认为是“栈顶”。

或者当你将内存视图切换到显示dword值时,为了避免在 head 中出现 little-endian,它会显示:

0000009C:  12345678 AABBCCDD ....
于 2017-11-15T02:42:02.990 回答