考虑x86指令ENTER
。来自英特尔的指令集参考。x86 ENTER指令有什么问题?
为过程创建堆栈帧。第一个操作数(大小为 操作数)指定堆栈帧的大小(即,为该过程在堆栈上分配的动态存储器的字节数 )。 第二个操作数(嵌套级别操作数)给出了过程的词法嵌套 级别(0到31)。嵌套级别确定从前一帧复制到新堆栈帧的“显示区域” 中的堆栈帧指针的数量。这两个 操作数都是立即值。
我想知道ENTER
指令如何作为第二个操作数传递非零嵌套级别。在这种情况下,根据英特尔的手册,处理器应该在堆栈上添加额外的帧指针。听起来很简单,但我不明白为什么它在示例程序中无法按预期工作。
我用FASM编译了下面的例子,并用OllyDbg进行调试。
format PE
section '.text' code readable executable
entry start
start:
enter 16, 8
push 0
call ExitProcess
...
ENTER
指令发出的堆栈帧如下所示。
000CFF58 00000000 ; new esp
000CFF5C 00000000
000CFF60 00000000
000CFF64 00000000
000CFF68 000CFF88 ; value of new ebp
000CFF6C 7EFDE000 ; ?
000CFF70 000CFF94 ; value of old ebp
000CFF74 76AD338A ; ?
000CFF78 7EFDE000 ; ?
000CFF7C 000CFF94 ; value of old ebp
000CFF80 76AD338A ; ?
000CFF84 7EFDE000 ; ?
000CFF88 000CFF94 ; value of old ebp
000CFF8C 76AD338A ; old esp
结果很奇怪。让我们用gcc做同样的事情。
> cat enter.s
.globl _start
.text
_start:
enter $16, $8
movl $1, %eax
movl $0, %ebx
int $0x80
> gcc -m32 -g -c enter.s && ld -melf_i386 enter.o
> gdb a.out
...
(gdb) r
...
Program received signal SIGSEGV, Segmentation fault.
_start() at enter.s:5
5 enter $16, $8
Errr,确定...
我可能误解它如何工作。我唯一的猜测是ENTER
指令是由OS以某种方式处理的,但这几乎肯定是错误的。
'进入'是x86指令集中许多坏主意之一,比如'loop [cc]'。很遗憾,AMD在定义x86-64时没有清除它。 – EOF 2014-11-22 17:11:55