编译.c文件成汇编.s文件

中间文件*.i,但实际工作中通常不用专门生成这种文件,因为基本上用不到;

若非要生成这种文件不可,可以利用下面的示例命令:

1
gcc -E test.c -o test.i

在编译阶段,输入的是中间文件*.i,编译后生成汇编语言文件*.s 。

这个阶段对应的GCC命令如下所示:

1
GCC -S test.i -o test.s

在汇编阶段,将输入的汇编文件*.s转换成机器语言*.o。

这个阶段对应的GCC命令如下所示:

1
GCC -c test.s -o test.o

.i文件和.s文件分析

.i文件和.s文件都是中间文件,用于编译器的中间过程。其中,.i文件是预处理后的C源代码文件,.s文件是汇编代码文件。

.i文件结构:

.i文件是经过预处理后的C源代码文件,其结构与C源代码文件类似,但是包含了宏定义、条件编译、头文件包含等预处理指令的展开结果。因此,.i文件的结构比C源代码文件更加复杂。以下是一个简单的.i文件示例:

1
2
3
4
5
6
7
8
9
10
# 1 "test.c"
# 1 "<built-in>"
# 1 "<命令行>"
# 1 "test.c"
int main() {
int a = 1;
int b = 2;
int c = a + b;
return c;
}

可以看到,.i文件的第一行是一个注释,表示这个文件是由哪个C源代码文件生成的。接下来的几行是预处理指令,用于展开宏定义和头文件包含等操作。最后是真正的C源代码。

.s文件结构:

.s文件是汇编代码文件,其结构与汇编代码类似。以下是一个简单的.s文件示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
	.file	"test.c"
.text
.globl main
.type main, @function
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ecx
subl $4, %esp
movl $1, -4(%ebp)
movl $2, -8(%ebp)
movl -4(%ebp), %eax
addl -8(%ebp), %eax
movl %eax, -12(%ebp)
movl -12(%ebp), %eax
movl %ebp, %esp
popl %ebp
leal -4(%eax), %esp
ret
.size main, .-main
.ident "GCC: (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0"
.section .note.GNU-stack,"",@progbits

在.s文件中,以.开头的行是指导编译器如何处理这个文件的伪指令。例如,.file指令表示这个文件是由哪个源代码文件生成的,.text指令表示下面的代码是程序的代码段,.globl指令表示下面的符号是全局可见的。接下来是程序的具体代码,每行都是一条汇编指令。最后几行是一些元数据,例如编译器的版本信息和栈的安全属性等。

总的来说,.i文件和.s文件都是编译器的中间文件,用于编译器的中间过程。.i文件是经过预处理后的C源代码文件,.s文件是汇编代码文件。它们的具体结构取决于编译器的实现。

版权所有,如有侵权请联系我