我正在学习汇编,我想了解如何使用C代码生成Assembly.
我创建了以下虚拟C代码:
#include <stdio.h>
int add(int x, int y){
int result = x + y;
return result;
}
int main(int argc, char *argv[]){
int x = 1 * 10;
int y = 2 * 5;
int firstArg = x + y;
int secondArg = firstArg / 2;
int value;
value = add(firstArg, secondArg);
return value;
}
Run Code Online (Sandbox Code Playgroud)
并得到以下汇编代码
.file "first.c"
.text
.globl add
.type add, @function
add:
.LFB39:
.cfi_startproc
movl 8(%esp), %eax
addl 4(%esp), %eax
ret
.cfi_endproc
.LFE39:
.size add, .-add
.globl main
.type main, @function
main:
.LFB40:
.cfi_startproc
movl $30, %eax
ret
.cfi_endproc
.LFE40:
.size main, .-main
.ident "GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2"
.section .note.GNU-stack,"",@progbits
Run Code Online (Sandbox Code Playgroud)
而且我很惊讶所有那些主要的算术运算都消失了?我不明白我们是如何从无处获得30美元的(好吧,我想它是来自add函数的返回值,但是为什么我没有看到任何得到这个值的命令,实际上我看到返回值已被推送到eax in添加功能,为什么我们需要再次将30美元转移到eax?).所有当地主要货物都在哪里申报?我特意创建了其中的5个以查看如何将其推入堆栈.
你能帮我理解那些是什么吗.LFE39 .LFB40:.LFB39:是什么意思?
我准备好了这本书,但它并没有为我澄清这个案子.实际上书说所有功能必须从堆栈初始化开始:
pushl %ebp
movl %esp, %ebp
Run Code Online (Sandbox Code Playgroud)
当函数结束时,它需要用pop指令完成它.
在上面的代码中不是这种情况.我没有看到任何堆栈初始化.
谢谢!
Jon*_*art 13
您正在编译并启用了优化.GCC足够聪明,可以在编译时执行所有这些计算,并用一个简单的常量替换所有无用的代码.
首先,x和y将被替换为自己的常量表达式:
int x = 10;
int y = 10;
Run Code Online (Sandbox Code Playgroud)
然后,使用这些变量的位置将获得其常量值:
int firstArg = 20;
int secondArg = 10;
Run Code Online (Sandbox Code Playgroud)
接下来,您的add功能很小而且微不足道,因此它肯定会被内联:
value = firstArg + secondArg;
Run Code Online (Sandbox Code Playgroud)
现在这些也是常量,所以整个事情将被替换为:
int main(int argc, char *argv[]) {
return 30;
}
Run Code Online (Sandbox Code Playgroud)
虽然大多数函数都会有一个像你所展示的序幕,但你的程序除了返回30之外什么都不做.更具体地说,它不再使用任何局部变量,也不会调用其他函数.因为这main不需要调用堆栈上的帧或保留空间.所以编译器不需要发出序言/尾声.
main:
movl $30, %eax
ret
Run Code Online (Sandbox Code Playgroud)
这些是程序运行的唯一两条指令(除了C运行时启动代码).
请注意,由于您的add功能未标记static,编译器必须假设外部有人可能会调用它.出于这个原因,我们仍然add在生成的程序集中看到,即使没有人调用它:
add:
movl 8(%esp), %eax
addl 4(%esp), %eax
ret
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
212 次 |
| 最近记录: |