【发布时间】:2014-12-17 06:32:15
【问题描述】:
所以我用 C 创建汇编代码并尝试了解它是如何工作的。我需要你的帮助来澄清一些观点,并告诉我我是否正在以正确的方式分析装配工作。
这里是C代码
int mult(int x, int y){
int result = x * y;
return result;
}
int main(int argc, char *argv[]){
int x = 10;
int y = 2;
return mult(x, y);
}
这里是生成的程序集
mult:
.LFB0:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
subl $16, %esp
movl 8(%ebp), %eax
imull 12(%ebp), %eax
movl %eax, -4(%ebp)
movl -4(%ebp), %eax
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
main:
.LFB1:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
subl $24, %esp
movl $10, -8(%ebp)
movl $2, -4(%ebp)
movl -4(%ebp), %eax
movl %eax, 4(%esp)
movl -8(%ebp), %eax
movl %eax, (%esp)
call mult
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
那么我如何理解上述程序集: 1. pushl %ebp - 我们先 push ebp,它将指向我们主堆栈的底部 2. movl %esp, %ebp - 不完全确定它是什么,但我假设我们只是为 esp 提供与 ebp 中相同的地址 3. subl $24, %esp - 我们给出 esp 6 个块(4 个字节)的地址。这意味着 esp 将具有第 6 个块的地址(这里我不确定我是否以正确的方式放置了 esp)。我在下面展示了我的堆栈
......
ebp
......
......
......
......
......
......
特别
......
- movl $10, -8(%ebp) - 所以我们将 10 放入堆栈底部的第二个块中
......
ebp
......
......
10
......
......
......
......
特别
......
- movl $2, -4(%ebp) 我们把 2 放在栈底的第一个块中
......
ebp
......
2
......
10
......
......
......
......
特别
......
- movl -4(%ebp), %eax - 我们将 2 放入 eax
......
ebp
......
2
......
10
......
......
......
......
特别
......
- movl %eax, 4(%esp) - 我们把 2 从 eax 放到栈顶的第一个块
......
ebp
......
2
......
10
......
......
......
2
......
特别
......
- movl -8(%ebp), %eax - 我们将 10 放入 eax
......
ebp
......
2
......
10
......
......
......
2
......
特别
......
- movl %eax, (%esp) - 我们将 eax 中的 10 放入 esp ......
ebp
......
2
......
10
......
......
......
2
......
10
......
留
......
- 调用 mult - 我们调用函数 mult。
所以,据我所知,我们准备了 2 和 10 作为参数,将它们移到堆栈的最顶部。然后我们将返回地址推到参数之后的最顶部。所以返回地址之后的下一个块将被 mult 函数的 ebp 占用。对吗?
不过,我不明白为什么我们有 2 个块(意思是 -12(%ebp) 和 -16(%ebp))是空的? 我在 Assembly 中没有看到任何与这 2 个 8 字节块有关的代码。为什么 main 堆栈被分配了 24 个字节,而不是 16 个字节? 1. pushl %ebp 多: ......
2
......
10
......
留
......
ebp
......
不确定是什么 .cfi_def_cfa_offset 8 .cfi_offset 5, -8 这里的意思是……它告诉我们什么? 我也不确定 movl %esp, %ebp 是做什么的。它将esp地址复制到ebp? 我知道这是基本的堆栈启动。
subl $16, %esp 。 esp 的地址是第 4 个块。
......
2
......
10
......
留
......
ebp
......
......
......
......
特别
......
- movl 8(%ebp), %eax
所以这里我们将 10 复制到 eax
imull 12(%ebp), %eax 然后我们将第二个参数 2 与 eax 中的 10 相乘。
movl %eax, -4(%ebp) 然后我们将结果从 eax 移动到 mult 函数的堆栈中 .............
2
......
10
......
留
......
ebp
......
20
......
......
......
特别
......
-
-4(%ebp), %eax 然后我们又把它移回eax?我们为什么要这样做? 不确定这两条指令的用途:
movl %eax, -4(%ebp) movl -4(%ebp), %eax
他们互相取消了......不是吗?
抱歉,发了很长的帖子。如果您能澄清我的分析错误的地方并澄清以上一些令人困惑的地方,我将不胜感激。
【问题讨论】:
-
至少,去掉一些空白。
-
请重新格式化此问题,以免其过长。另外,我希望你只在
main中返回mult的结果,作为本练习的一部分——main应该真正使用适当且有意义的返回值。在这种情况下就像EXIT_SUCCESS。 -
@MikeW 如果我去掉一些空格,一切都会一团糟。如果项目之间没有空格,Stack Overflow 会将所有内容放在一行中。
-
@FemX:这不是唯一的方法。请看:stackoverflow.com/help/formatting
-
@IskarJarak 我将如何重新格式化它?不幸的是,我在 Stack Overflow 编辑窗口中没有找到任何表格视图,所以我无法以任何其他方式表示堆栈...我在每条指令之后特别显示堆栈,因为我不确定我是否以正确的方式分析所有内容