- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
所以我们有以下代码,设置一个带参数的函数调用,省略主体(等等等等),然后在函数末尾弹出。
pushl %ebp
movl %esp, %ebp
pushl %ebx
movl 8(%ebp), %ebx
movl 12(%ebp), %ecx
etc
etc
etc
//end of function
popl %ebx
popl %ebp
这是我(认为)我理解的。
假设我们有 %esp 指向内存地址 100。
pushl %ebp
所以这基本上使 %ebp 指向 %esp 指向的位置(内存地址 100)+ 4。所以现在 %ebp 指向内存地址 104。这使我们当前的内存状态看起来像这样:
----------
|100|%esp
|104|%ebp
----------
然后我们有下一行代码:
movl %esp, %ebp
所以据我了解,ebp 现在指向内存地址 100。我对为什么要执行此步骤有一点直觉,但我的困惑是下一行:
pushl %ebx
推送 ebx 的目的是什么,我假设它会指向内存地址 104?我对 ebp (104) 正下方的空间应该如何引用“旧堆栈指针”有一个模糊的想法,所以我可以理解为什么接下来的两行将 8 和 12 添加到 ebp 作为“参数”我们的功能,而不是 4 和 8。
但我对为什么我们首先将 ebx 压入堆栈感到困惑。
我也不明白popping,为什么要pop ebx和ebp?
在他不得不 sleep 之前与某人谈论这个,他提到我们没有引用我们的堆栈指针是 100 的事实——直到我们弹出 ebp 回来。现在,我认为 ebp 的值(value)是 100,所以我不明白他试图表达的观点。
所以澄清一下:
到目前为止,我的理解是否正确?
为什么我们要将 ebx 压入堆栈?
位于 ebp 正下方的“对旧堆栈指针的引用”是什么?那是我们推的 ebx 吗?
有没有我不明白的地方,比如我们推送的 ebx 和紧跟在(我们的论点)之后的行中的 ebx 之间的某种区别?被推送的 ebp 和紧随其后的行中的 ebp 有区别吗?
为什么我们在最后弹出?
如果这很难理解,我深表歉意。我知道有人问过类似的问题,但我试图以一种对我有意义的方式直观地理解和描绘函数调用中到底发生了什么。
注意:我编辑了一些关于我对正在发生的事情的理解的重要内容,特别是关于 ebp。
最佳答案
正如约阿希姆所说 in a comment关于你的问题,压入一个寄存器会将寄存器的内容压入栈中;它不会推送对寄存器或其他任何内容的引用。我不确定你是不是说这就是发生的事情,否则这张图就不清楚了:
----------
|100|%esp
|104|%ebp
----------
不过,我会尝试解释它的作用和原因。
假设 %esp
是 0x100
当调用者调用我们的函数并且 call
之后的指令是 0x200
。当我们执行 call
时,我们压入 0x200
(返回地址)并跳转到该过程。那么我们的堆栈是:
Address Value
%esp --> 0x100 0x200
%ebp
是某个值或其他值;它可能指向堆栈,也可能不指向堆栈。它甚至不需要表示地址。所以 %ebp
在这一点上对我们来说毫无意义。
但是虽然它对我们没有意义,调用者确实希望它在调用前后保持不变,所以我们必须保留它。假设它包含值 0xDEADBEEF
。我们推送它,所以堆栈现在看起来像这样:
Address Value
0x100 0x 200
%esp --> 0x0fc 0xDEADBEEF
在大多数情况下,我们可以将所有内容都作为 %esp
的偏移量来处理,这也适用于此。但是如果编译器正在编译一些处理可变长度数组或其他特性的 C 代码,我们通常会希望从我们推送的第一件事而不是我们推送的最后一件事开始索引。为此,我们将 %ebp
设置为我们现在所在的位置。然后事情看起来像这样:
Address Value
0x100 0x 200
%esp, %ebp --> 0x0fc 0xDEADBEEF
请注意,%ebp
指向的地址处的值是 %ebp
的旧值,因此您可以遍历堆栈,正如您提到的那样之前的。
接下来,我们推送 %ebx
,我们称其值为 0xBEEFCAFE
。这是与函数序言没有直接关系的第一件事。然后我们的堆栈看起来像这样:
Address Value
0x100 0x 200
%ebp --> 0x0fc 0xDEADBEEF
%esp --> 0x0f8 0xBEEFCAFE
但为什么我们要推送 %ebx
?好吧,事实证明,x86 C 调用约定规定,与 %ebp
一样,%ebx
必须保持调用前的状态。因此,由于您省略的代码可能会更改 %ebx
,因此它必须保留初始值,以便为调用者恢复它。
在我们恢复 %ebx
之后,我们弹出 %ebp
,同时恢复它的值,因为那也必须是调用后保存。最后我们回来了。
TL;DR %ebp
和 %ebx
被压入和弹出,因为它们在函数体的执行过程中被操纵, 但 x86 C 调用约定规定调用前后值必须保持相同,因此必须保留初始值以便我们可以恢复它们。
关于c - 了解 x86 IA32 程序集中函数调用的前/后汇编代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25173836/
我尝试理解[c代码 -> 汇编]代码 void node::Check( data & _data1, vector& _data2) { -> push ebp -> mov ebp,esp ->
我需要在当前表单(代码)的上下文中运行文本文件中的代码。其中一项要求是让代码创建新控件并将其添加到当前窗体。 例如,在Form1.cs中: using System.Windows.Forms; ..
我有此 C++ 代码并将其转换为 C# (.net Framework 4) 代码。有没有人给我一些关于 malloc、free 和 sprintf 方法的提示? int monate = ee; d
我的网络服务器代码有问题 #include #include #include #include #include #include #include int
给定以下 html 代码,将列表中的第三个元素(即“美丽”一词)以斜体显示的 CSS 代码是什么?当然,我可以给这个元素一个 id 或一个 class,但 html 代码必须保持不变。谢谢
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
我试图制作一个宏来避免重复代码和注释。 我试过这个: #define GrowOnPage(any Page, any Component) Component.Width := Page.Surfa
我正在尝试将我的旧 C++ 代码“翻译”成头条新闻所暗示的 C# 代码。问题是我是 C# 中的新手,并不是所有的东西都像 C++ 中那样。在 C++ 中这些解决方案运行良好,但在 C# 中只是不能。我
在 Windows 10 上工作,R 语言的格式化程序似乎没有在 Visual Studio Code 中完成它的工作。我试过R support for Visual Studio Code和 R-T
我正在处理一些报告(计数),我必须获取不同参数的计数。非常简单但乏味。 一个参数的示例查询: qCountsEmployee = ( "select count(*) from %s wher
最近几天我尝试从 d00m 调试网络错误。我开始用尽想法/线索,我希望其他 SO 用户拥有可能有用的宝贵经验。我希望能够提供所有相关信息,但我个人无法控制服务器环境。 整个事情始于用户注意到我们应用程
我有一个 app.js 文件,其中包含如下 dojo amd 模式代码: require(["dojo/dom", ..], function(dom){ dom.byId('someId').i
我对“-gencode”语句中的“code=sm_X”选项有点困惑。 一个例子:NVCC 编译器选项有什么作用 -gencode arch=compute_13,code=sm_13 嵌入库中? 只有
我为我的表格使用 X-editable 框架。 但是我有一些问题。 $(document).ready(function() { $('.access').editable({
我一直在通过本教程学习 flask/python http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-wo
我想将 Vim 和 EMACS 用于 CNC、G 代码和 M 代码。 Vim 或 EMACS 是否有任何语法或模式来处理这种类型的代码? 最佳答案 一些快速搜索使我找到了 this vim 和 thi
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 想改进这个问题?更新问题,使其成为 on-topic对于堆栈溢出。 7年前关闭。 Improve this
这个问题在这里已经有了答案: Enabling markdown highlighting in Vim (5 个回答) 6年前关闭。 当我在 Vim 中编辑包含 Markdown 代码的 READM
我正在 Swift3 iOS 中开发视频应用程序。基本上我必须将视频 Assets 和音频与淡入淡出效果合并为一个并将其保存到 iPhone 画廊。为此,我使用以下方法: private func d
pipeline { agent any stages { stage('Build') { steps { e
我是一名优秀的程序员,十分优秀!