在一些教程中,据说堆栈指针指向堆栈的顶部元素:
+-------------+
| stack |
+-------------+
| top element | <-- esp
+-------------+
在其他人中,据说它指向它后面,所以第一个内存地址可以在堆栈增长时写入。
+-------------+
| stack |
+-------------+
| top element |
+-------------+ <-- esp
在这个德国Wickipedia网站上 https://de.wikipedia.org/wiki/Register_(Computer)#Stapelregister 据说两个版本都存在,并且它取决于CPU架构。
我的问题是,它是如何在x86-CPU上运行的?它还取决于操作系统吗?
答案 0 :(得分:2)
让我们假设您处于32b x86模式,并且您将地址100到200的内存保留为堆栈(不真实,太低,会与IVT发生冲突,但会为此示例)。堆栈中已经存在一些值,因此esp
为160。
现在&#34;堆栈值的顶部&#34;占用地址160,161,162和163处的存储器(四个字节,因为在32b模式中,堆栈中的单个值是32b = 4B大),让我们说存储值0xaabbccdd
。
如果您现在push 0x12345678
,则CPU将首先从esp
- &gt;中减去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
值0×12345678。
最后,当您在推送后查看调试器中的内存,从ss:esp
地址查看它时,它将包含这些字节(hexa):
0000009C: 78 56 34 12 DD CC BB AA ....
(0x9C = 156 =内存视图开始的地址)。 esp
点在值的第一个字节处,被认为是&#34;堆栈顶部&#34;。
或者当您将内存视图切换为显示dword
值时,为避免小头编写,请显示:
0000009C: 12345678 AABBCCDD ....