64位CPU运行32位代码时栈取值为何用esp+4而非esp+8?
解答
你的认知误区在于默认64位x86 CPU执行所有代码时,PUSH指令都会压入64位数据——这个结论只在CPU运行64位长模式下的64位代码时成立,和你当前的运行场景完全不符。
你的环境是用32位编译器编译程序,最终生成的是32位x86指令,这类程序在64位Windows上会通过WoW64兼容层运行,此时CPU会切换到32位保护模式工作:该模式下默认操作数宽度为4字节,栈指针使用32位的esp寄存器,PUSH指令执行时只会把栈指针减4,再写入4字节的操作数,根本不会按64位规则压8字节数据。
你这段代码的实际栈变化过程如下:
- 初始状态:
esp指向当前栈顶 - 执行
push 11:esp = esp - 4,将11写入esp指向的4字节栈空间,此时栈顶存储值为11 - 执行
push 22:esp = esp - 4,将22写入新的栈顶位置,此时栈空间的布局为:esp + 0(当前栈顶):存储22esp + 4:存储第一次压入的11
push 11 push 22 mov eax, [esp+4] ; 取到esp偏移4位置的11,完全符合32位栈操作逻辑
补充说明:哪怕CPU运行在64位长模式下,PUSH的操作宽度也不是固定8字节——可以通过指令前缀显式指定压入4字节数据,不存在“64位CPU执行PUSH总会压64位数据”的绝对规则,指令的操作数宽度由运行模式、代码段配置、指令前缀共同决定。
内容的提问来源于stack exchange,提问作者Teddy
相关产品推荐
相关产品推荐

