在 x86-CPU 上,堆栈指针究竟指向(!)哪里?到顶部元素还是在它后面?
Where exactly(!) does the stack pointer point to on x86-CPUs? TO the top element or RIGHT BEHIND it?
在一些教程中说栈指针指向栈顶元素:
+-------------+
| stack |
+-------------+
| top element | <-- esp
+-------------+
在其他人中,它指向它的右后方,因此指向堆栈增长时可以写入的第一个内存地址。
+-------------+
| stack |
+-------------+
| top element |
+-------------+ <-- esp
在这个德国维基百科网站上
https://de.wikipedia.org/wiki/Register_(Computer)#Stapelregister
据说这两个版本都存在,而且它依赖于CPU架构。
我的问题是,它在 x86-CPUs 上怎么样?它也取决于操作系统吗?
假设您处于 32b x86 模式,并且您将地址 100 到 200 的内存保留为堆栈(不真实,太低,会与 IVT 冲突,但在本示例中会这样做)。堆栈中已经有一些值,所以 esp
是 160.
现在"top of the stack value"在地址160、161、162和163处占用内存(四个字节,因为在32b模式下,堆栈中的单个值是32b = 4B大),假设有存储值0xaabbccdd
.
如果您现在执行 push 0x12345678
,CPU 将首先从 esp
中减去 4 -> 新的 esp = 156; (160-4)
。然后它将写入 32b 值,以小端方式分解为四个字节: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
指向值的第一个字节,被认为是 "top of stack".
或者切换内存视图显示dword
值时,为了避免head中的little-endian组合,它会显示:
0000009C: 12345678 AABBCCDD ....
在一些教程中说栈指针指向栈顶元素:
+-------------+
| stack |
+-------------+
| top element | <-- esp
+-------------+
在其他人中,它指向它的右后方,因此指向堆栈增长时可以写入的第一个内存地址。
+-------------+
| stack |
+-------------+
| top element |
+-------------+ <-- esp
在这个德国维基百科网站上 https://de.wikipedia.org/wiki/Register_(Computer)#Stapelregister 据说这两个版本都存在,而且它依赖于CPU架构。
我的问题是,它在 x86-CPUs 上怎么样?它也取决于操作系统吗?
假设您处于 32b x86 模式,并且您将地址 100 到 200 的内存保留为堆栈(不真实,太低,会与 IVT 冲突,但在本示例中会这样做)。堆栈中已经有一些值,所以 esp
是 160.
现在"top of the stack value"在地址160、161、162和163处占用内存(四个字节,因为在32b模式下,堆栈中的单个值是32b = 4B大),假设有存储值0xaabbccdd
.
如果您现在执行 push 0x12345678
,CPU 将首先从 esp
中减去 4 -> 新的 esp = 156; (160-4)
。然后它将写入 32b 值,以小端方式分解为四个字节: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
指向值的第一个字节,被认为是 "top of stack".
或者切换内存视图显示dword
值时,为了避免head中的little-endian组合,它会显示:
0000009C: 12345678 AABBCCDD ....