所以我从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 - 我们首先推动ebp,它将指向我们主堆栈的底部 2. movl%esp,%ebp - 不完全确定它是什么,但我假设我们只为epp中的esp提供相同的地址 3. subl $ 24,%esp - 我们给出esp 6块(4字节)的地址。这意味着esp将具有第6个块的地址(这里我不确定我是否以正确的方式放置esp)。我在下面展示了我的堆栈
.............
EBP
.............
.............
.............
.............
.............
.............
尤
.............
.............
EBP
.............
.............
10
.............
.............
.............
.............
尤
.............
.............
EBP
.............
2
.............
10
.............
.............
.............
.............
尤
.............
.............
EBP
.............
2< --- eax
.............
10
.............
.............
.............
.............
尤
.............
.............
EBP
.............
2< --- eax
.............
10
.............
.............
.............
2
.............
尤
.............
.............
EBP
.............
2
.............
10< --- eax
.............
.............
.............
2
.............
尤
.............
EBP
.............
2
.............
10< --- eax
.............
.............
.............
2
.............
10<< --- esp
.............
保留
.............
所以,据我所知,我们准备2和10作为参数,将它们移动到堆栈的最顶层。然后我们在参数后面的顶部推送了返回地址。因此返回地址后的下一个块将被多功能的ebp占用。正确的吗?
虽然,我不明白为什么我们有2个区块(意思是-12(%ebp)和-16(%ebp))为空? 我没有在Assembly中看到任何困扰那些2个8字节块的代码。为什么然后堆栈的主要分配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
.............
.............
.............
.............
esp<< ----
.............
所以这里我们将10复制到eax
imull 12(%ebp),%eax然后我们取第二个参数2并将其乘以10中的eax。
movl%eax,-4(%ebp)然后我们将结果从eax移动到多功能堆栈 .............
2
.............
10
.............
保留
.............
EBP
.............
20<< ----
.............
.............
.............
尤
.............
-4(%ebp),%eax然后我们再次将其移回eax?我们为什么要这样做? 不确定这两条指令的目的是什么:
movl%eax,-4(%ebp) movl -4(%ebp),%eax
他们互相取消..不?
很抱歉很长的帖子。如果你能澄清我的分析错误的地方并澄清上面的一些令人困惑的问题,我将感激不尽。
答案 0 :(得分:0)
您在分析的第1步和第2步中处于领先地位。
pushl %ebp ;save ebp on the stack.
...
movl %esp, %ebp ;point ebp to the stack to access arguments and local variable space.
...
movl %eax, -4(%ebp) ;move the product to result
movl -4(%ebp), %eax ;return result
未优化,但这就是函数mult()
的作用。