考虑x86指令ENTER.来自英特尔的指令集参考.
为过程创建堆栈帧.第一个操作数(大小操作数)指定堆栈帧的大小(即,为该过程在堆栈上分配的动态存储的字节数).第二个操作数(嵌套级别操作数)给出过程的词法嵌套级别(0到31).嵌套级别确定从前一帧复制到新堆栈帧的"显示区域"的堆栈帧指针的数量.这两个操作数都是立即值.
我想知道ENTER当非零嵌套级别作为第二个操作数传递时,指令是如何工作的.在这种情况下,根据英特尔的手册,处理器应该在堆栈上推送额外的帧指针.听起来很简单,但我无法理解为什么它在样本程序中无法正常工作.
我使用FASM编译了以下示例,并使用OllyDbg进行了调试.
format PE
section '.text' code readable executable
entry start
start:
enter 16, 8
push 0
call ExitProcess
...
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
结果很奇怪.让我们用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
Run Code Online (Sandbox Code Playgroud)
呃,好的......
我可能误解了它应该如何工作.我唯一的猜测是,ENTER操作系统以某种方式处理指令,但这几乎肯定是错误的.
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
Run Code Online (Sandbox Code Playgroud)
另请参见6.5.1 ENTER指令在英特尔®64和IA-32架构软件开发人员手册卷1:基本架构
| 归档时间: |
|
| 查看次数: |
957 次 |
| 最近记录: |