我对大会全新,并希望确认在以下陈述中我有哪些误解,需要纠正。
堆栈指针(ESP
)指的是堆栈的顶部(最低内存地址)。
基本指针(EBP
)用于在构建堆栈帧时临时存储各种内存地址。它通常保存当前堆栈帧的最高内存地址。
指令指针(EIP
)是指内存文本(代码)段中一行代码的内存地址
一旦某些东西被推入堆栈,它就无法就地更改。即。如果我们PUSH EBP
到堆栈,我们正在推送EBP
的当前值,而不是某种引用或指向它的指针。然后,我们无法就地更改该值。
传递给函数的参数通常被移动到地址空间,该地址空间是堆栈指针的偏移量。即。 [ESP-12]
。
调用函数时(使用CALL
),会发生以下情况:
EIP
之后的地址的内存中,因此我们知道在被调用函数完成后返回的位置感谢。我试图理解这些东西。
答案 0 :(得分:7)
传递给函数的参数通常被移动到地址空间,该地址空间是堆栈指针的偏移量。即。 [ESP-12]。
通常,参数会被推入堆栈,在之前。
push paramA ; ( some 32bit value, register, whatever )
push paramB
call myFunct
这导致以下堆栈内容:
---------------
| paramA |
---------------
| paramB |
---------------
| return addr | <-- ESP
---------------
由于返回地址(由call
推送)为4个字节,因此该函数的参数为[ESP+4]
和[ESP+8]
。
如果你的函数添加了一个堆栈框架,通常你会这样做
myFunct: push EBP
mov EBP, ESP
现在堆栈看起来像这样:
---------------
| paramA |
---------------
| paramB |
---------------
| return addr |
---------------
| saved EBP | <-- EBP, ESP
---------------
并且参数位于[EBP+8]
和[EBP+12]
,即使您推送更多值(或为局部变量添加一些位置),因为EBP
不再更改:
myFunct: push EBP
mov EBP, ESP
sub ESP, 12 ; make room for 3 32bit local variables
mov eax, [EBP+8] ; access one of the parameters
mov [EBP-4], eax ; save it in local variable #1
rel | rel |
to | to |
ESP | EBP |
----|------|--------------
+24 | +12 | paramA |
| |--------------
+20 | +8 | paramB |
| |--------------
+16 | +4 | return addr |
| |--------------
+12 | | saved EBP | <-- EBP (is fixed here for now)
| |---------------
+8 | -4 | local#1 |
| |---------------
+4 | -8 | local#2 |
| | ---------------
0 | -12 | local#3 | <--- ESP (keeps growing, by pushing, calling etc)
---------------
局部变量位于[EBP-4]
,[EBP-8]
,[EBP-12]
等
返回地址位于[EBP+4]
注意:如您所见,可能
ESP
访问(然后你不需要一个帧指针,但是你需要跟踪你推送了多少数据,以“找到”参数和变量)EBP
(其中包括一些开销)。在许多函数中,根本不需要帧指针,并且由编译器优化掉。答案 1 :(得分:4)
一旦某些东西被推入堆栈,它就无法就地更改。即。如果我们将EBP推入堆栈,我们正在推动EBP的当前值,而不是某种引用或指向它的指针。 我们无法就地更改该值。
当然可以。堆栈是普通的计算机内存,没有什么特别之处,除了99%的代码需要OriginalSource
中的有效(读取+写入访问)内存地址和一些保留空间,因此它可以将一些本地内容推送到它,如需要的。
esp
几乎相当于:
push ebp ; store current value in ebp to stack
(但第二个变体也会修改标志,而且它的原子性稍差)
现在你可以用其他任何东西覆盖它,比如:
sub esp,4
mov [esp],ebp
引用或指向它的指针
嗯,没有办法给mov [esp],eax ; overwrite the old_ebp value with current_eax value
寄存器提供某种引用或指针,它是CPU中的一个寄存器,只有32位(32x 0或1值)并且它没有地址,你可以工作仅在说明中使用其名称ebp
,允许在编码中使用它。
在ebp
时,将这32位(并且没有其他信息)复制到存储器中(然后保存那些以其自己的32位= 4字节复制的0/1值)。没有信息记录内存中的值,何时以及通过什么指令只存储值位。