- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想了解有关堆栈的更多信息。特别是,调用带参数的函数时会发生什么。为此,我编写了以下代码:
#include <stdio.h>
int sum(int d, int e, int f){
int result = d + e + f;
return result;
}
int main(void){
int a = 5;
int b = 4;
int c = 2;
int erg = sum(a,b,c);
printf("Result is: %d", erg);
}
我得到以下汇编代码(我只会添加main
函数的部分,因为首先我想了解这部分):
push ebp,
mov ebp, esp
and esp, -16
sub esp, 32
mov DWORD PTR[esp+28], 5
mov DWORD PTR[esp+24], 4
mov DWORD PTR[esp+20], 2
mov eax, DWORD PTR[esp+20]
mov DWORD PTR[esp+8], eax
mov eax, DWORD PTR[esp+24]
mov DWORTD PTR[esp+4], eax
mov eax, DWORD PTR[esp+28]
mov DWORD PTR[esp], eax
call sum
........
........
因此,对于这一部分,我为自己画了一个小草图。请看一下 :)我的问题:那时我的 ebp
在哪里?由于我的汇编代码的第 2 行,它必须在与 [esp]
相同的位置,对吗?
现在,我的第二个问题之后的 sum 函数部分。
所以这是它的汇编代码:
push ebp
mov ebp, esp
sub esp, 16
mov eax, DWORD PTR[ebp+12]
mov edx, DWORD PTR[ebp+8]
mov edx, eax
------------
所以,我了解到我们总是可以在 [eb+12]
和 [ebp+8]
中找到我们的参数。(我跳过了第三个参数,因为我想保持简单)所以我现在的问题是:如果我假设 esp
=ebp
并查看我的草图,然后我发现 [esp+12]
或现在没有任何内容[ebp+12]
。但是,尽管如此,它还是被使用了。我怎么能想象得到呢?
有人可以帮助我吗?我读了很多论文,但似乎没有人勾勒出这些东西。因此,很难理解这一点。
谢谢!
这是我的草图:
最佳答案
在第一个函数执行期间,esp
和 ebp
只有在指令 mov ebp, esp
之后才具有相同的值。之后and esp, -16
将esp
的最低4位(最低半字节)归零,esp
和ebp
发散,除非 esp
的最低位已经为零。然后 sub esp, 32
从 esp
中减去 32,这里 esp
和 ebp
肯定会发散。
push ebp ; esp = esp - 4; [esp] = ebp.
mov ebp, esp ; ebp = esp. create the stack frame.
and esp, -16 ; make lowest 4 bits of esp zeros, for alignment.
sub esp, 32 ; esp = esp - 32. make space for local variables.
mov DWORD PTR[esp+28], 5 ; a = 5
mov DWORD PTR[esp+24], 4 ; b = 4
mov DWORD PTR[esp+20], 2 ; c = 2
mov eax, DWORD PTR[esp+20] ; eax = c (eax = 2)
mov DWORD PTR[esp+8], eax ; [esp+8] = dword 2
mov eax, DWORD PTR[esp+24] ; eax = b (eax = 4)
mov DWORTD PTR[esp+4], eax ; [esp+4] = dword 4
mov eax, DWORD PTR[esp+28] ; eax = a (eax = 5)
mov DWORD PTR[esp], eax ; [esp] = dword 5
call sum ; the above lines define the parameters for the
; function sum, that is called now.
那么关于你的第二个问题:
push ebp ; esp = esp - 4; [esp] = ebp.
mov ebp, esp ; ebp = esp.
sub esp, 16 ; esp = esp - 16. create space for local variables.
; at this point:
; [ebp] == old value of ebp.
; [ebp+4] == return address pushed by call,
; to be used by the next ret.
; [ebp+8] == dword 5 (a)
; [ebp+12] == dword 4 (b)
; [ebp+16] == dword 2 (c)
mov eax, DWORD PTR[ebp+12] ; eax = 4
mov edx, DWORD PTR[ebp+8] ; edx = 5. gets overwritten by the next instruction.
mov edx, eax ; edx = eax = 4
不要假设 esp
== ebp
。在第二个函数中,esp
和 ebp
也在执行指令 sub esp,16
时发生分歧。学习使用调试器,例如 GDB 和单步执行代码,并在每条指令后跟踪寄存器(尤其是 esp
)和内存的值。您也可以像我上面那样在头脑中调试代码,但如果您是汇编初学者,使用调试器通常会容易得多,而且不容易出错。
关于assembly - 使用带参数的函数在堆栈中的 ebp 和 esp 行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20695203/
回车和有什么区别 push ebp mov ebp, esp sub esp, imm 说明?有性能差异吗?如果是这样,哪个更快,为什么编译器总是使用后者? 与离开和类似 mov esp, eb
我有以下 NASM 汇编程序,运行时间约为 9.5 秒: section .text global _start _start: mov eax, 0 mov ebx, 8 loop:
根据互联网上的许多教程,据说您可以找到以下结构的命令行参数: 然而,在花一些时间测试我为 NASM 编写的汇编代码后,我发现 ESP 的值是一些数字,例如: -144807325 实际参数计数存储在更
1. 设备烧录的程序rainmaker自带gpio示例 2. swaggerapis登录账户 3. 调用Rainmaker封装好的py
文章结构: 项目概述 成品预览 项目框架 硬件资料,代码 项目槽点 -项目
我是一个学习汇编的初学者,在函数调用之前保留 ESP 寄存器时,通过加法或减法来实现是否重要?很难解释,请考虑以下内容 mov esi, esp sub esp, 12 // on 32bit OS
我反汇编了一个小程序,该程序询问用户的姓名,然后输出“Hello + [user's_name]” 这是反汇编的输出: 主要功能: 打招呼功能: 我注意到,对于 main() 函数,ESP 寄存器递减
我正在从事 Visual Studio 项目项目 A(在编译时生成静态库) 有课 using namespace mynamespace; class projectAclass { virtua
从上图中可以看出,函数setAttribute 时发生了错误。从它的调用返回。 有谁知道如何解决图中显示的这个错误?我知道这是调用约定之间的错误,但是如何找出 setAttribute 的调用约定是什
我用 QT 制作了一个 .dll 文件并将其加载到我的应用程序中。当它即将从一个函数返回时,我收到: The value of ESP was not properly saved across a
我找不到答案。从我读到的 %ebp 有 32 位,将 %esp 移动到 %ebp 你仍然有 32 位,然后减去 70 到 32,我不明白其余的。我对此很陌生,所以我不是很精通。请给出详细的解释。谢谢!
我有一个从 c 程序调用的简单汇编函数,我必须使用需要内存操作数的指令( FIDIV )。 将值移动到 [esp - 2] 是否安全并在下一条指令中使用它,或者以这种方式使用堆栈永远不会安全? 我知道
以下陈述有什么区别? mov %eax,%esp mov %eax,(%esp) 我正在努力散布一个二元炸弹,但在处理一些 mov 时遇到了问题。和 leal在程序集的早期命令。 最佳答案 这会将 %
我使用 duinotech XC-3800 在 ESP32 芯片上使用 ESP IDF 测试运行裸机代码,并在图像大小方面获得以下结果。 ESP32 的分析二进制大小 文件夹结构 温度/ 主要的/ C
我正在 OS X(32 位)上执行系统调用,如下所示: push 123 mov eax, 1 sub esp, 4 int 0x80 而且我不太明白 sub esp, 4 间隙。 我在某处读到,BS
当我在 gdb 中反汇编 main() 时,它会重新调整此结果: 0x0804854c : push ebp 0x0804854d : mov ebp,esp 0x0804
我目前正在学习英特尔处理器的汇编。既然堆栈“向下增长”,为什么我们必须添加才能访问特定元素 [ebp + 8] ;; This will access the first param 我知道我们必须跳
我试图了解如何将堆栈与程序集一起使用,在我尝试时,我在 SO 中的一个问题中遇到了以下代码,即: push ecx mov eax, 4 mov ebx, 1 mov ecx, result m
我有这个 C 代码部分: #include void main() { int n, array[1000], c, d, t, e; char step; puts("Enter a number
我不太明白为什么 gcc 在调用函数之前要先将 esp 减去 12。 pushl %ebp movl %esp,%ebp sub $12,%esp socke
我是一名优秀的程序员,十分优秀!