x86 ENTER指令有什么问题?

时间:2014-11-22 16:17:22

标签: assembly x86

考虑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

呃,好吧......

我可能误解了它应该如何运作。我唯一的猜测是操作系统以某种方式处理ENTER指令,但这几乎肯定是错误的。

1 个答案:

答案 0 :(得分:5)

enter指令的嵌套形式假设您已经在ebp中有一个有效的帧指针,这在进程开始时不是linux的情况。大概这就是你犯错的原因。

请改为尝试:

_start:
    enter $0, $0        # set up initial stack frame
    push $1
    push $2             # simulate two previous frame pointers
    enter $16, $3       # nested proc level 3, esp should be 32 less
    movl (%ebp), %eax   # should be previous ebp
    movl -4(%ebp), %eax # should be 1
    movl -8(%ebp), %eax # should be 2
    movl $1, %eax
    movl $0, %ebx
    int $0x80

另请参阅Intel®64和IA-32架构软件开发人员手册第1卷:基本架构

中的 6.5.1 ENTER Instruction 部分