Linux GCC 常用命令与汇编

文章目录

  • Linux GCC 常用命令与汇编
    • 1 、简介
    • 2 、简单编译
      • 2.1 预处理
      • 2.2 编译为汇编代码
      • 2.3 汇编(Assembly)
      • 2.4 连接(Linking)
    • 3 、多个程序文件
    • 4、 检错
    • 5 、库文件连接
      • 5.1 编译成可执行文件
      • 5.2 链接
      • 5.3 强制链接时使用静态链接库
    • 6、汇编
    • 7、链接
    • 8、分析ELF文件
      • 8.1ELF 文件的段
      • 8.2反汇编 ELF

1 、简介

GCC 的意思也只是 GNU C Compiler 而已。经过了这么多年的发展,GCC 已经不仅仅能支持 C 语言;它现在还支持 Ada 语言、C++ 语言、Java 语言、Objective C 语言、Pascal 语言、COBOL 语言,以及支持函数式编程和逻辑编程的 Mercury 语言,等等。而 GCC 也不再单只是 GNU C 语 言编译器的意思了,而是变成了 GNU Compiler Collection 也即是 GNU 编译器家族的意思了。另 一方面,说到 GCC 对于操作系统平台及硬件平台支持,概括起来就是一句话:无所不在

2 、简单编译

#include <stdio.h>
int main(void)
{printf("Hello World!\n");
return 0;
}

这个程序,一步到位的编译指令是:

gcc test.c -o test

实质上,上述编译过程是分为四个阶段进行的,即预处理(也称预编译,Preprocessing)、编译 (Compilation)、汇编 (Assembly)和连接(Linking)

2.1 预处理
gcc -E test.c -o test.i 或 gcc -E test.c

gcc 的-E 选项,可以让编译器在预处理后停止,并输出预处理结果

2.2 编译为汇编代码

预处理之后,可直接对生成的 test.i 文件编译,生成汇编代码:

 gcc -S test.i -o test.s

生成的汇编程序 hello.s 的代码片段如下

gcc 的-S 选项,表示在程序编译期间,在生成汇编代码后,停止,-o 输出汇编代

2.3 汇编(Assembly)

对于上一小节中生成的汇编代码文件 test.s,gas 汇编器负责将其编译为目标文件,如下:

 gcc -c test.s -o test.o

2.4 连接(Linking)

gcc 连接器是 gas 提供的,负责将程序的目标文件与所需的所有附加的目标文件连接起来,最终生 成可执行文件。附加的目标文件包括静态连接库和动态连接库。

对于上一小节中生成的 test.o,将其与C标准输入输出库进行连接,最终生成程序 test

 gcc test.o -o test

在命令行窗口中,执行./test

3 、多个程序文件

通常整个程序是由多个源文件组成的,相应地也就形成了多个编译单元,使用 GCC 能够很好地管理 这些编译单元。假设有一个由 test1.c 和 test2.c 两个源文件组成的程序,为了对它们进行编译,并 最终生成可执行程序 test,可以使用下面这条命令:

 gcc test1.c test2.c -o test

如果同时处理的文件不止一个,GCC 仍然会按照预处理、编译和链接的过程依次进行。如果深究起 来,上面这条命令大致相当于依次执行如下三条命令:

 gcc -c test1.c -o test1.o gcc -c test2.c -o test2.o gcc test1.o test2.o -o test

4、 检错

gcc -pedantic illcode.c -o illcode -pedantic

编译选项并不能保证被编译程序与 ANSI/ISO C 标准的完全兼容,它仅仅只能用来帮助 Linux 程序员离这个目标越来越近。或者换句话说,-pedantic 选项能够帮助程序员发现一些不符合 ANSI/ISO C 标准的代码,但不是全部,事实上只有 ANSI/ISO C 语言标准中要求进行编译器诊断的 那些情况,才有可能被 GCC 发现并提出警告。

除了-pedantic 之外,GCC 还有一些其它编译选项也能够产生有用的警告信息。这些选项大多以-W 开头,其中最有价值的当数-Wall 了,使用它能够使 GCC 产生尽可能多的警告信息。

gcc -Wall illcode.c -o illcode

GCC 给出的警告信息虽然从严格意义上说不能算作错误,但却很可能成为错误的栖身之所。一个优 秀的 Linux 程序员应该尽量避免产生警告信息,使自己的代码始终保持标准、健壮的特性。所以将 警告信息当成编码错误来对待,是一种值得赞扬的行为!所以,在编译程序时带上-Werror 选项,那 么 GCC 会在所有产生警告的地方停止编译,迫使程序员对自己的代码进行修改,如下:

 gcc -Werror test.c -o test

5 、库文件连接

5.1 编译成可执行文件

首先我们要进行编译 test.c 为目标文件,这个时候需要执行

 gcc –c –I /usr/dev/mysql/include test.c –o test.
5.2 链接

最后我们把所有目标文件链接成可执行文件:

 gcc –L /usr/dev/mysql/lib –lmysqlclient test.o –o test

Linux 下的库文件分为两大类分别是动态链接库(通常以.so 结尾)和静态链接库(通常以.a 结尾), 二者的区别仅在于程序执行时所需的代码是在运行时动态加载的,还是在编译时静态加载的

5.3 强制链接时使用静态链接库

默认情况下, GCC 在链接时优先使用动态链接库,只有当动态链接库不存在时才考虑使用静态链 接库,如果需要的话可以在编译时加上-static 选项,强制使用静态链接库。

在/usr/dev/mysql/lib 目录下有链接时所需要的库文件 libmysqlclient.so 和 libmysqlclient.a,为了让 GCC 在链接时只用到静态链接库,可以使用下面的命令:

gcc –L /usr/dev/mysql/lib –static –lmysqlclient test.o -o test

静态库链接时搜索路径顺序:

  1. ld 会去找 GCC 命令中的参数-L

  2. 再找 gcc 的环境变量 LIBRARY_PATH

  3. 再找内定目录 /lib /usr/lib /usr/local/lib 这是当初 compile gcc 时写在程序内的

    动态链接时、执行时搜索路径顺序:

    1.编译目标代码时指定的动态库搜索路径

    2.环境变量 LD_LIBRARY_PATH 指定的动态库搜索路径

    3.配置文件/etc/ld.so.conf 中指定的动态库搜索路径

    4.默认的动态库搜索路径/lib

    5.默认的动态库搜索路径/usr/lib

    有关环境变量:

    LIBRARY_PATH 环境变量:指定程序静态链接库文件搜索路径

    LD_LIBRARY_PATH 环境变量:指定程序动态链接库文件搜索路

6、汇编

汇编过程调用对汇编代码进行处理,生成处理器能识别的指令,保存在后缀为.o 的目标文件中。由于每一个汇编语句几乎都对应一条处理器指令,因此,汇编相 对于编译过程比较简单,通过调用 Binutils 中的汇编器 as 根据汇编指令和处理 器指令的对照表一一翻译即可。

当程序由多个源代码文件构成时,每个文件都要先完成汇编工作,生成.o 目标 文件后,才能进入下一步的链接工作。注意:目标文件已经是最终程序的某一部 分了,但是在链接之前还不能执行。

使用 gcc 进行汇编的命令如下:

$ gcc -c hello.s -o hello.o

// 将编译生成的 hello.s 文件汇编生成目标文件 hello.o

// GCC 的选项-c 使 GCC 在执行完汇编后停止,生成目标文件

//或者直接调用 as 进行汇编 $ as -c hello.s -o hello.o

//使用 Binutils 中的 as 将 hello.s 文件汇编生成目标文件

注意:hello.o 目标文件为 ELF(Executable and Linkable Format)格式的可 重定向文件。

7、链接

链接也分为静态链接和动态链接

(1) 静态链接是指在编译阶段直接把静态库加入到可执行文件中去,这样可执行 文件会比较大。链接器将函数的代码从其所在地(不同的目标文件或静态链 接库中)拷贝到最终的可执行程序中。为创建可执行文件,链接器必须要完 成的主要任务是:符号解析(把目标文件中符号的定义和引用联系起来)和 重定位(把符号定义和内存地址对应起来然后修改所有对符号的引用)。

(2) 动态链接则是指链接阶段仅仅只加入一些描述信息,而程序执行时再从系统 中把相应动态库加载到内存中去。

 在 Linux 系 统中,gcc 编 译链 接时 的动 态库 搜索 路径 的 顺序 通常 为:首 先从 gcc 命 令的 参 数-L 指 定的 路径 寻找 ;再 从环 境变 量 LIBRARY_PATH 指 定的 路径 寻址;再 从默 认路 径 /lib、/usr/lib、 /usr/local/lib 寻找 。

 在 Linux 系 统中,执 行二 进制 文件 时的 动态 库搜 索路 径的 顺序 通常 为:首 先搜 索编 译目 标 代码 时指 定的 动态 库搜 索路 径;再 从环 境变 量 LD_LIBRARY_PATH 指 定的 路径 寻址;再 从 配置 文件/etc/ld.so.conf 中 指定 的动 态库 搜索 路径 ;再 从默 认路 径/lib、/usr/lib 寻找 。

 在 Linux 系统 中, 可以 用 ldd 命令 查看 一个 可执 行程 序依 赖的 共享 库。

由于链接动态库和静态库的路径可能有重合,所以如果在路径中有同名的静态库文件和动 态库文件,比如 libtest.a 和 libtest.so,gcc 链接时默认优先选择动态库,会链接 libtest.so,如果要让 gcc 选择链接 libtest.a 则可以指定 gcc 选项-static,该选项会强 制使用静态库进行链接。

如果使用命令“gcc test.c -o test”则会使用动态库进行链接,生成的 ELF 可执行文件的大小(使用 Binutils 的 size 命令查看)和链接的动态库 (使用 Binutils 的 ldd 命令查看)如下所示

gcc test.c -o test
 size test   使用 size 查看大小

 ldd test  可以看出该可执行文件链接了很多其他动态库,主要是 Linux 的 glibc
动态库

如 果 使 用 命 令 “ gcc -static test.c -o test”则 会 使 用 静 态 库 进 行 链 接 , 生成的 ELF 可执行文件的大小(使用 Binutils 的 size 命令查看)和链接的 动态库(使用 Binutils 的 ldd 命令查看)

 gcc -static test.c -o testsize test

可以看出 text 的代码尺寸 变得极大

8、分析ELF文件

8.1ELF 文件的段

ELF 文件格式如下图所示,位于 ELF Header 和 Section Header Table 之间的都 是段(Section)。一个典型的 ELF 文件包含下面几个段:

.text:已编译程序的指令代码段。

.rodata:ro 代表 read only,即只读数据(譬如常数 const)。

.data:已初始化的 C 程序全局变量和静态局部变量。

.bss:未初始化的 C 程序全局变量和静态局部变量。

.debug:调试符号表,调试器用此段的信息帮助调试。

可以使用 readelf -S 查看其各个 section 的信息如下:

 readelf -S test

8.2反汇编 ELF

由于 ELF 文件无法被当做普通文本文件打开,如果希望直接查看一个 ELF 文件包 含的指令和数据,需要使用反汇编的方法。

使用 objdump -D 对其进行反汇编如下:

 objdump -D test

使用 objdump -S 将其反汇编并且将其 C 语言源代码混合显示出来:

 $ gcc -o test -g test.c //要加上-g 选项$ objdump -S test


ELF

由于 ELF 文件无法被当做普通文本文件打开,如果希望直接查看一个 ELF 文件包 含的指令和数据,需要使用反汇编的方法。

使用 objdump -D 对其进行反汇编如下:

 objdump -D test

使用 objdump -S 将其反汇编并且将其 C 语言源代码混合显示出来:

 $ gcc -o test -g test.c //要加上-g 选项$ objdump -S test

Linux GCC 常用命令相关推荐

  1. Linux GCC常用命令和ELF文件格式

    Linux GCC常用命令和ELF文件格式 一.各种工具 (一)GCC编译工具 (二)Binutils (三)C 运行库 一. C 语言程序 Hello.c示例 (一)准备工作 (二)编译过程 1.预 ...

  2. Linux GCC常用命令

    目录 一.示例一 1.简单编译 1.1预处理 1.2编译为汇编代码 1.3汇编 1.4连接 2.多个程序文件的编译 3检错 4库文件连接 二.示例二 1.准备hello.c 2.预处理 3.编译 4. ...

  3. linux中gcc是什么指令,Linux gcc常用命令

    gcc的编译过程分为四个过程,即预处理(也称预编译,Preprocessing).编译(Compilation).汇编 (Assembly)和连接(Linking). 例如,编译文件test.c,那么 ...

  4. GCC常用命令与nasm

    目录 一.Linux GCC 常用命令 简单编译 预处理 编译为汇编代码(Compilation) 汇编(Assembly) 连接(Linking) 多个程序文件的编译 检错 库文件链接 编译成可执行 ...

  5. gcc常用命令与gcc编译器背后的故事

    目录 1 gcc常用命令 1.1 简介 1.2 简单编译 1.2.1 预处理 1.2.2 编译为汇编代码(Compilation) 1.2.3 汇编(Assembly) 1.2.4 连接(Linkin ...

  6. GCC常用命令及GCC编译器背后的故事

    文章目录 一. GCC常用命令 1. 简介 2. 简单编译 2.1 预处理 2.2 编译为汇编代码(Compilation) 2.3 汇编(Assembly) 2.4 连接(Linking) 3. 多 ...

  7. linux的编程命令,linux编程常用命令

    学习linux编程最基本的就是要掌握常用的编程命令,下面由学习啦小编为大家整理了linux编程常用命令相关知识,希望大家喜欢! linux编程常用命令1.编译应用程序 make -f makefile ...

  8. linux指令笔试,Linux笔试常用命令

    Linux笔试常用命令 时间:2019-01-01 [www.unjs.com - 资料大全] 文件操作命令 ls 作用:列目录,Linux笔试常用命令>(https://www.unjs.co ...

  9. linux find -size参数,Linux find 常用命令

    Linux find 常用命令 (2012-10-24 11:32:52) 标签: linux shell 说明: 以下内容,若标注在 [ ] 中括号内的均可省略,除非做特别说明. 但严格来说,若缺少 ...

最新文章

  1. mysql 重要监控参数_mysql 的重要参数,监控需要
  2. Remoting 技术
  3. python安装numpy库用清华镜像_Mac下基于Anaconda通过清华镜像安装Tensorflow
  4. Java SpringMVC实现PC端网页微信扫码支付完整版
  5. AI小白必读:深度学习、迁移学习、强化学习别再傻傻分不清
  6. 华强北万事俱备,只待 iPhone 11到货
  7. mvc% html.%,MVC的html.doc
  8. struts2 拦截器_Struts2令牌拦截器示例
  9. ASP.NET中进行消息处理(MSMQ) 一 (转)
  10. jQuery 选择器 (基础恶补之二)
  11. Android手机指纹驱动工作原理
  12. python教程视频全套下载-Python爬虫视频教程全集下载
  13. VMware虚拟机12个使用技巧
  14. 学校计算机实训室座次安排,班级座位调整流程设计
  15. 探秘varian:优雅的发布部署程序
  16. sqlite的可视化管理工具SQLite Expert
  17. 朋友介绍对象加微信后,对方不搭理你的真实原因都在这里面
  18. 四、指针高级应用总结
  19. aosp编译环境搭建
  20. AWS物联网解决方案之:如何将设备安全地接入AWS IoT

热门文章

  1. autohotkey 热键_键盘快捷方式(热键),用于将鼠标移至多显示器配置中的显示器-AutoHotkey脚本
  2. 2022 APMCM亚太数学建模竞赛 C题 全球是否变暖 问题一python代码实现(更新完毕)
  3. 大数据 - 指标 - 流量
  4. MATLAB 找到n阶方阵中对角线上的连续素数个数 不使用循环
  5. airbnb机器学习模型_机器学习基础:预测Airbnb价格
  6. TA-Lib介绍安装及使用教程
  7. pycharm 明明解释器里已经下载了sklearn,但还是显示找不到sklearn解决办法
  8. 湿度传感器行业调研报告 - 市场现状分析与发展前景预测
  9. 多思计算机组成原理实验八:简单模型机实验
  10. 报错:WARNING: Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after con