我目前正在学习高级汇编语言,并且一直在讨论堆栈的概念 . 我想我理解得很好,但在实践中我有一些问题 .
堆栈增长,ESP寄存器始终指向堆栈的顶部 . 低内存中的地址 . 如果有东西被推入堆栈,那么ESP应该递减 .
EBP用作帧指针,据我所知,应该总是超过ESP .
然而,通过以下计划:
stdout.put(esp, nl);
stdout.put(ebp, nl);
push(ike);
stdout.put(esp, nl);
stdout.put(ebp, nl);
push(ike);
stdout.put(esp, nl);
stdout.put(ebp, nl);
pop(eax);
pop(eax);
pop(eax);
pop(eax);
stdout.put(esp, nl);
stdout.put(ebp, nl);
似乎并非如此 . 看输出:
0018FF6C 0018FF70
0018FF68 0018FF70
0018FF64 0018FF70
0018FF74 0018FF70
EBP始终相同,ESP在第一次推送时递减4个字节,然后在第二次推送时递减4个字节 .
在此之后我很困惑 . 在我的前两次弹出后,ESP应该回到它开始的地方 . 如果我没有把任何东西推到堆栈上,怎么能再做两次pop?我弹出什么?
EAX的进一步弹出和打印显示一些数字,然后是0,然后是更多的数字 . 所以,我肯定会弹出一些东西......但是什么?我的程序存储器属于哪个部分,为什么没有受到影响?
为什么EBP根本没有受到影响?
另外,为什么ESP减少了4个字节,而不是8个?
如果有人能帮助我理解这一点,我将非常感激 .
2 回答
EBP不会被推/弹指令修改,它是手动设置的,所以除非你自己更改它,否则它将保持不变 .
IKE的推送导致4字节的更改,所以显然你在这里处于32位模式 .
EAX(32位)的4个弹出将导致16字节(10h)的更改,就像它们一样 .
不知道这里有什么问题 . 似乎按照我的预期工作?
除了你推送和弹出的东西之外,堆栈还用于保存每个函数's stack frame (i.e. local variables), return address, the old ebp (specifically where the current ebp is) and function'的参数 . 所以你弹出的是你的函数的堆栈框架 .
如果您反汇编程序,您会看到:
此时堆栈将是这样的:
最后,您只需按下并弹出4个字节,因为这是您机器的字大小,这样您就可以保存整个寄存器 . 一枪