加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

需要帮助理解从C代码生成的基本汇编代码

发布时间:2020-12-16 10:35:07 所属栏目:百科 来源:网络整理
导读:我正在学习汇编,我想了解如何使用C代码生成Assembly. 我创建了以下虚拟C代码: #include stdio.hint 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 se
我正在学习汇编,我想了解如何使用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;
}

并得到以下汇编代码

.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

而且我很惊讶所有那些主要的算术运算都消失了?
我不明白我们是如何从无处获得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    $30,%eax
    ret

这些是程序运行的唯一两条指令(除了C运行时启动代码).

还要注意,因为你的add函数没有标记为static,所以编译器必须假设外部有人可能会调用它.出于这个原因,我们仍然看到生成的程序集中的添加,即使没有人调用它:

add:
    movl    8(%esp),%eax
    ret

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读