12

我对pop组装中的实际作用感到困惑。是否pop将值ed 最后移到堆栈上(这意味着如果我们在最后一个元素 ed 之后的值PUSH不适用),或者它只是弹出堆栈上最后一个值(因此,同时适用于and ),或者确实它弹出堆栈指针指向的任何值?考虑以下代码:MOVPUSHMOVPUSH

push $4
mov $5, -4(%esp)
add $4, %esp (esp pointing to an unknown value)
pop %ebp

那么在这段代码中,弹出的值ebp是 4、5,还是 指向的未知值esp

4

2 回答 2

24

后者

POP EBP

相当于

MOV EBP, [ESP]
ADD ESP, 4           ; but without modifying flags, like  LEA ESP, [ESP+4]

(在 Intel 语法中 - 左侧为目标,右侧为源)

于 2014-09-24T20:53:28.967 回答
21

PUSH <src>做:

 ESP := ESP-4  ; for x86; -8 for x64
 MEMORY[ESP]:=<operandvalue>

POP <dst>做:

 <operandtarget>:=MEMORY[ESP];
 ESP:=ESP+4    ; for x86; +8 for x64

如果您将机器指令的描述写成这样的伪代码,则更容易理解机器指令的作用。英特尔参考手册中充满了此类伪代码,值得您花时间和精力去获取它们,并自己阅读详细信息。(例如,在 HTML 摘录中https://www.felixcloutier.com/x86/pushhttps://www.felixcloutier.com/x86/pop

关于您的具体问题:您的$5into存储-4(%esp)是有效的机器指令,处理器将毫无怨言地执行它,但这确实是非常不安全的编程。如果处理器在该指令之后发生陷阱或中断,则处理器状态(通常)保存在“堆栈顶部”,并将覆盖您的值。由于中断是异步发生的,因此您会看到很少会丢失 5 美元的行为。这使得调试程序非常困难。

"add $4" 将 ESP 移回push 指令之前的位置。因此,您不能对弹出到 ebp 中的值说任何话,除非它是“未知”的,正如您建议的选项之一。

请参阅Raymond Chen 的博客,了解为什么在 ESP 下编写即使在 Windows 下的用户空间也是不安全的。(中断不会异步使用用户空间堆栈,但有些东西可以。)在非 Windows 上,POSIX 信号处理程序可以踩到用户空间 ESP 下方的空间。(除了在 x86-64 System V 中,ABI 定义了一个低于 RSP 的 128 字节的“红色区域”,可以安全使用。)

于 2014-09-24T21:01:03.983 回答