关于编译、汇编和链接

1 GCC的命令格式

gcc [options] [filenames]

序号选项含义
1-E只做预处理
2-c只做编译,不进行链接,目的是为了生成目标文件“.o”
3-S生成汇编代码
4-o file将输出生成的内容保存至file描述的的文件中
5-g在输出文件中加入支持调试的信息
6-v显示输出详细的命令执行过程信息

2 GCC的执行步骤

1、编译(cc1,cc1是C语言的编译器):编译器完成“预处理”和“编译”,“预处理”主要指的是处理源文件中以“#”开头的预处理指令,比如#include、#define等;“编译”则针对预处理的结果进行一系列的词法分析、语法分析、语义分析,优化后生成汇编指令,存放在.o为后缀的目标文件中。

2、汇编(as):汇编器将汇编语言代码转换为CPU可以执行的指令。

3、链接(ld):链接器将汇编器生成的目标文件和一些标准库(比如libc)文件组合,形成最终可执行的应用程序。

3 ELF文件格式

ELF文件格式简介_elf文件格式详解-CSDN博客文章浏览阅读1.3w次,点赞12次,收藏117次。  简单了解下ELF文件的格式。1 简介  可执行与可链接格式 (Executable and Linkable Format,ELF),常被称为 ELF格式,是一种用于可执行文件、目标代码、共享库和核心转储(core dump)的标准文件格式,一般用于类Unix系统,比如Linux,Macox等。ELF 格式灵活性高、可扩展,并且跨平台。比如它支持不同的字节序和地址范围,所以它不会不兼容某一特别的 CPU 或指令架构。这也使得 ELF 格式能够被运行于众多不同平台的各种操作系统所广泛采纳。  E._elf文件格式详解https://blog.csdn.net/GrayOnDream/article/details/124564129?ops_request_misc=&request_id=&biz_id=102&utm_term=progbits&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-8-124564129.nonecase&spm=1018.2226.3001.4187

Linux- 浅谈ELF目标文件格式_linux elf文件-CSDN博客文章浏览阅读1k次。理解了进程的描述和创建之后,自然会想到我们编写的可执行程序是如何作为一个进程工作的?这就涉及可执行文件的格式、编译、链接和装载等相关知识。 这里先提一个常见的名词“目标文件”,是指编译器生成的文件。“目标”指目标平台, 例如 x86 或 x86-64,它决定了编译器使用的机器指令集。目标文件一般也叫作 ABI(Application Binary Interface,应用程序二进制接口),目标文件和目标平台是二进制兼容的。二进制兼容 即指该目标文件已经是适应某一种 CPU 体系结构上的二进制指_linux elf文件https://blog.csdn.net/weixin_43844521/article/details/129811818?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522170799590216800182773873%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=170799590216800182773873&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-15-129811818-null-null.142%5Ev99%5Epc_search_result_base2&utm_term=progbits&spm=1018.2226.3001.4187

练习1:

1、编写⼀个简单的打印 “hello, world!” 的程序源文件: hello.c

vim hello.c


2、对源文件进⾏本地编译,⽣成针对⽀持x86_64指令集架构处理器的⽬标文件hello.o

gcc -c hello.c -o hello.o

其中-o hello.o可以省略,不指定输出文件名的话,会默认生成同名的hello.o

3、查看hello.o的文件的文件头信息

readelf -h hello.o

4、查看hello.o的Section header table

readelf -SW hello.o

5、对hello.o反汇编,并查看hello.c的C程序源码和机器指令的对应关系

gcc -g -c hello.c

objdump -S hello.o

练习2:

#include <stdio.h>
    int global_init = 0x11111111;
    const int global_const = 0x22222222;
void main()
{
    static int static_var = 0x33333333;
    static int static_var_uninit;
    int auto_var = 0x44444444;
    printf("hello world!\n");
    return;
}

请问编译为.o文件后,global_init, global_const, static_var, static_var_uninit, auto_var这些变量分别存放在那些section⾥,"hello world!\n"这个字符串⼜在哪⾥?

global_init:存放在.data中。由于它被初始化了,所以会存放在.data中。 
global_const:存放在.rodata中,因为它是一个常量,不可修改。
static_var:存放在.data中。由于它是一个静态变量且被初始化了,所以会存放在.data中。
static_var_uninit:存放在.bss中,因为它是一个静态变量但未被初始化,.bss存放未初始化的全局和静态变量。 
auto_var:在函数内部声明的局部变量通常存放在栈上,而不是.o文件中的sections中。 
"hello world!\n":存放在.rodata中,因为它是一个常量字符串,不可修改。

验证:

gcc -g -c test.c

objdump -S test.o

objdump -s test.o

如上所示:
int global_init = 0x11111111,static int static_var = 0x33333333,存放在.data中。
const int global_const = 0x22222222,"hello world!\n",存放在.rodata中。
static int static_var_uninit,未被初始化,但int类型的变量通常占用4个字节,因此可以合理确认存放在.bss中。
int auto_var = 0x44444444,存放在堆栈上,可以看到被放置在rbp指向的地址。

  • 18
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值