假设我们写了一个C代码文件 code.c包含下面代码:

int accum = 0;

int sum(int x, int y)
{
int t = x + y;
accum += t;
return t;
}
这是用echo命令输入源码的效果,简单的就是最好的:)

一、查看GCC生成的汇编代码
在命令行上用“-S”选项,就能看到C编译器产生的汇编代码:
#gcc -S code.c

注意:这里是大写的-S,如果用小写gcc会说找不到main函数

会在当前目录下生成code.s文件,直接打开即可

这段汇编代码没有经过优化:

.file "code.c"
.globl _accum
.bss
.align 4
_accum:
.space 4
.text
.globl _sum
.def _sum; .scl 2; .type 32; .endef
_sum:
pushl %ebp
movl %esp, %ebp
subl $4, %esp # 为局部变量t在栈帧上分配空间
movl 12(%ebp), %eax # %eax <- y
addl 8(%ebp), %eax # %eax <- x + y
movl %eax, -4(%ebp) # t <- x +y
movl -4(%ebp), %eax # %eax <- t
addl %eax, _accum # _accum <- t + _accum
movl -4(%ebp), %eax # %eax <- t
leave # 平衡堆栈: %esp <- %ebp , popl %ebp
ret

下面是使用“-O2”选项开启二级优化的效果:

#gcc -O2 -S code.c

.file "code.c"
.globl _accum
.bss
.align 4
_accum:
.space 4
.text
.p2align 4,,15 # 使下一条指令的地址从16的倍数处开始,
.globl _sum # 最多浪费15个字节
.def _sum; .scl 2; .type 32; .endef
_sum:
pushl %ebp # 保存原%ebp
movl %esp, %ebp
movl 12(%ebp), %eax # %eax <- y
movl 8(%ebp), %edx # %edx <- x
popl %ebp # 恢复原%ebp
addl %edx, %eax # %eax <- x + y
addl %eax, _accum # _accum <- _accum + x + y
ret

GCC产生的汇编代码有点难读,它包含一些我们不关心的信息。所有以 "." 开头的行都是指导汇编器和链接器的命令,称为“汇编器命令”。

代码中已经除去了所有关于局部变量名或数据类型的信息,但我们还是看到了一个对全局变量_accum的引用,这是因为编译器还不能确定这个变量会放在存储中的哪个位置。
二、用GDB查看目标文件的字节表示

首先,我们用反汇编器来确定函数sum的代码长度是19字节。然后我们在文件code.o上运行GNU调试工具GDB,输入命令:
(gdb) x/19xb sum
这条命令告诉GDB检查(简写为"x")19个以十六进制格式表示的字节。
三、反汇编目标文件

在Linux系统中,带 "-d" 命令行选项调用OBJDUMP可以完成这个任务:
#objdump -d code.o

从这里可以看出函数sum的代码长度正好是19字节。
四、生成实际可执行的代码
这需要对一组目标文件运行链接器,而这一组目标代码文件中必须包含有一个Main函数。在 main.c 中有这样的函数:
int main()
{
return sum(1,2);
}
然后,我们用如下方法生成可执行文件:
#gcc -O2 -o prog code.o main.c
再反汇编:
objdump -d prog
00401050 <_sum>:
401050: 55 push %ebp
401051: 89 e5 mov %esp,%ebp
401053: 8b 45 0c mov 0xc(%ebp),%eax
401056: 8b 55 08 mov 0x8(%ebp),%edx
401059: 5d pop %ebp
40105a: 01 d0 add %edx,%eax
40105c: 01 05 10 20 40 00 add %eax,0x402010
401062: c3 ret
这段代码与code.c反汇编产生的代码几乎完全一样。一个主要的区别是左边列出的地址不同。第二个不同之处在于链接器终于确定了存贮全局变量accum的地址。地址由原来的0x0变成了现在的0x402010

GCC生成的汇编代码的更多相关文章

  1. 【JVM】-NO.110.JVM.1 -【hsdis jitwatch 生成查看汇编代码】

    Style:Mac Series:Java Since:2018-09-10 End:2018-09-10 Total Hours:1 Degree Of Diffculty:5 Degree Of ...

  2. 使用hsdis查看jit生成的汇编代码

     http://blog.csdn.net/unei66/article/details/26477629 JVM 有 HotSpot引擎可以对热代码路径进行有效的 JIT优化,大幅度提升计算密集代码 ...

  3. linux 下gcc生成intel汇编

    留作备忘: gcc -S -masm=intel xxxx.c 生成elf可执行文件: gcc -o xxx xxxx.s 反汇编 objdump xxx 补充: 在使用gcc 对C语言程序进行编译时 ...

  4. 利用hsdis和JITWatch查看分析HotSpot JIT compiler生成的汇编代码

    http://blog.csdn.net/hengyunabc/article/details/26898657

  5. 分析一个C语言程序生成的汇编代码-《Linux内核分析》Week1作业

    署名信息 郭春阳 原创作品转载请注明出处 :<Linux内核分析>MOOC课程 http://mooc.study.163.com/course/USTC-1000029000 C源码 这 ...

  6. 程序编码(机器级代码+汇编代码+C代码+反汇编)

    [-1]相关声明 本文总结于csapp: 了解详情,或有兴趣,建议看原版书籍: [0]程序编码 GCC调用了一系列程序,将源代码转化成可执行代码的流程如下: (1)C预处理器扩展源代码,插入所有用#i ...

  7. 解析c语言背后的汇编代码

    源码 很简单的c语言代码,作用是交换两个数: #include <stdio.h> void swap(int * a, int * b) { *a = *a + *b - (*b = * ...

  8. 通过反汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的

    实验一:通过反汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的 学号:20135114 姓名:王朝宪 注: 原创作品转载请注明出处   <Linux内核分析>MOOC课程http: ...

  9. 汇编语言---GCC内联汇编

    转:http://www.cnblogs.com/taek/archive/2012/02/05/2338838.html GCC支持在C/C++代码中嵌入汇编代码,这些代码被称作是"GCC ...

随机推荐

  1. Oracle函数:求两个数的最小公倍数

    CREATE or replace function GetGbs(num1 NUMBER,num2 NUMBER) RETURN NUMBER is resultnum NUMBER; maxnum ...

  2. Flash AIR14导出ipa到Mac上的iOS模拟器测试

    没错!你没看错!俺这篇博客就是关于Flash AIR的! ----------------无聊的分割线------------------ 朋友最近学习Flash AIR for iOS开发,想找我帮 ...

  3. 标准的TCP/IP工业以太网-EtherNet/IP

    标准的TCP/IP工业以太网-EtherNet/IP                            徐智穹以太网具有传输速度高.兼容性好.应用广泛等方面的优势,支持几乎所有流行的网络协议,其中 ...

  4. 问题:如何在固定大小的DIV层插入N多个图片

    这是贴友问的一个问题,具体需求是: 如何在固定大小的DIV层插入N多个图片,使其一行排列,超出层宽时出现滑动条? 原以为利用overflow属性可以实现,但是测试失败.后来利用div层叠实现了效果. ...

  5. 基于samba实现win7与linux之间共享文件_阳仔_新浪博客

    基于samba实现win7与linux之间共享文件_阳仔_新浪博客 然后启动samba执行如下指令: /dev/init.d/smb start 至此完成全部配置.

  6. Android权威编程指南读书笔记(1-2章)

    第一章 Android应用初体验 1.4用户界面设计 <?xml version="1.0" encoding="utf-8"?> ADT21开发版 ...

  7. iOS: ARC和非ARC下使用Block属性的问题

    1. Block的声明和线程安全 Block属性的声明,首先需要用copy修饰符,因为只有copy后的Block才会在堆中,栈中的Block的生命周期是和栈绑定的,可以参考之前的文章(iOS: 非AR ...

  8. SQL中EXISTS的用法和效率

    比如在Northwind数据库中有一个查询为SELECT c.CustomerId,CompanyName FROM Customers cWHERE EXISTS(SELECT OrderID FR ...

  9. 【Stage3D学习笔记续】山寨Starling(七):一般优化方法简介及混合模式

    关于事件的优化: 遍历注册的事件由foreach改变为fori,在大量数据遍历时会有提升: 事件池优化: 所有的事件都使用一个对象池进行保存,而不是使用到时进行创建,使用EventDispatcher ...

  10. Oracle管道函数示例

    Oracle的管道函数需要定义下面的三样: Record/Object Type:定义一个Record或Object类型的变量,这个变量用于表示返回结果集的一行数据,有点像C#中的DataRow类. ...