我创建了以下虚拟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;}
并得到以下汇编代码
.file "first.c" .text .globl add .type add,@functionadd:.LFB39: .cfi_startproc movl 8(%esp),%eax addl 4(%esp),%eax ret .cfi_endproc.LFE39: .size add,.-add .globl main .type main,@functionmain:.LFB40: .cfi_startproc movl ,%eax ret .cfi_endproc.LFE40: .size main,.-main .IDent "GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2" .section .note.GNU-stack,"",@progbits
而且我很惊讶所有那些主要的算术运算都消失了?
我不明白我们是如何从无处获得30美元的(好吧,我想它是来自add函数的返回值,但是为什么我没有看到任何获取此值的命令,实际上我看到返回值已经被推送到eax in添加功能,为什么我们需要再次将30美元转移到eax?).
所有当地主要货物都在哪里申报?我特意创建了其中的5个以查看如何将其推入堆栈.
你能帮我理解那些是什么吗.LFE39 .LFB40:.LFB39:是什么意思?
我准备好了这本书,但它并没有为我澄清这个案子.
实际上书说所有功能必须从堆栈初始化开始:
pushl %ebp movl %esp,%ebp
当函数结束时,它需要用pop指令完成它.
在上面的代码中不是这种情况.我没有看到任何堆栈初始化.
谢谢!
解决方法 您正在编译并启用了优化. GCC足够聪明,可以在编译时执行所有这些计算,并用一个简单的常量替换所有无用的代码.首先,x和y将被替换为它们的常量表达式:
int x = 10; int y = 10;
然后,使用这些变量的位置将获得其常量值:
int firstArg = 20; int secondArg = 10;
接下来,你的add函数很小而且很简单,所以它肯定会被内联:
value = firstArg + secondArg;
现在这些也是常量,所以整个事情将被替换为:
int main(int argc,char *argv[]) { return 30;}
虽然大多数函数都会有一个像你所展示的序幕,但你的程序除了返回30之外什么都不做.更具体地说,它不再使用任何局部变量,也不会调用其他函数.因为这个主要不需要调用堆栈上的帧或保留空间.所以编译器不需要发出序言/尾声.
main: movl ,%eax ret
这些是程序运行的唯一两条指令(除了C运行时启动代码).
还要注意,因为你的add函数没有标记为static,所以编译器必须假设外部有人可能会调用它.出于这个原因,我们仍然看到生成的程序集中的添加,即使没有人调用它:
add: movl 8(%esp),%eax ret总结
以上是内存溢出为你收集整理的需要帮助理解从C代码生成的基本汇编代码全部内容,希望文章能够帮你解决需要帮助理解从C代码生成的基本汇编代码所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)