预编译、编译、汇编、链接

嵌入式_预编译、编译、汇编、链接

写下第一个hello word!! C语言程序,在集成开发环境中,只需点击编译按钮就能一键生成可执行程序,整个过程看似波澜不惊,但是其编译器却像过山车一样。从代码到可执行文件大致可分为4部分:预编译,编译,汇编,链接。



前言

话不多,上干货


一、 预编译

预编译:预编译的作用是把程序中的宏定义、头文件全部展开、处理条件编译的真假值、去掉注释等作用,最后预编译得到的是一个纯净的C文件。
在gcc中利用gcc -E xxx.c -o xxx.i得到预编译后的文件。
下面来对test.c文件进行预编译:

代码如下(示例):

#include <stdio.h>
#include <stdlib.h>


#define  MAXOPTIONS 100
#define  MAXVal     20

/*fun*/
int fun(void)
{
	printf("fun !");
}

/*mian.c*/
int main(int argc, char **argv)
{
     int value;
     printf("main");

     return 0;
}

得到预编译文件test.i如下(示例):

# 1 "test.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "test.c"
# 1 "/usr/include/stdio.h" 1 3 4
# 27 "/usr/include/stdio.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/bits/libc-header-start.h" 1 3 4
# 33 "/usr/include/x86_64-linux-gnu/bits/libc-header-start.h" 3 4
# 1 "/usr/include/features.h" 1 3 4
# 424 "/usr/include/features.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 1 3 4
# 427 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4
# 428 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 2 3 4
# 1 "/usr/include/x86_64-linux-gnu/bits/long-double.h" 1 3 4
# 429 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 2 3 4
# 425 "/usr/include/features.h" 2 3 4
# 448 "/usr/include/features.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 1 3 4
# 10 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/gnu/stubs-64.h" 1 3 4
# 11 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 2 3 4
# 449 "/usr/include/features.h" 2 3 4
# 34 "/usr/include/x86_64-linux-gnu/bits/libc-header-start.h" 2 3 4
# 28 "/usr/include/stdio.h" 2 3 4


# 1 "/usr/lib/gcc/x86_64-linux-gnu/7/include/stddef.h" 1 3 4
# 216 "/usr/lib/gcc/x86_64-linux-gnu/7/include/stddef.h" 3 4

# 216 "/usr/lib/gcc/x86_64-linux-gnu/7/include/stddef.h" 3 4
typedef long unsigned int size_t;
# 34 "/usr/include/stdio.h" 2 3 4

# 1 "/usr/include/x86_64-linux-gnu/bits/types.h" 1 3 4
# 27 "/usr/include/x86_64-linux-gnu/bits/types.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4
# 28 "/usr/include/x86_64-linux-gnu/bits/types.h" 2 3 4



.
.
.
.




# 9 "test.c"
int fun(void)
{
 printf("fun !");
}


int main(int argc, char **argv)
{
     int value;
     printf("main");

     return 0;
}

二、编译

编译:分析语法语义,优化后生成相应的汇编代码文件,最复杂最核心的步骤
gcc -S test.c -o test.s 得到汇编.s文件

代码如下(示例):

	.file	"test.c"
	.text
	.section	.rodata
.LC0:
	.string	"fun !"
	.text
	.globl	fun
	.type	fun, @function
fun:
.LFB5:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	leaq	.LC0(%rip), %rdi
	movl	$0, %eax
	call	printf@PLT
	nop
	popq	%rbp
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE5:
	.size	fun, .-fun
	.section	.rodata
.LC1:
	.string	"main"
	.text
	.globl	main
	.type	main, @function
main:
.LFB6:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	subq	$16, %rsp
	movl	%edi, -4(%rbp)
	movq	%rsi, -16(%rbp)
	leaq	.LC1(%rip), %rdi
	movl	$0, %eax
	call	printf@PLT
	movl	$0, %eax
	leave
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE6:
	.size	main, .-main
	.ident	"GCC: (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0"
	.section	.note.GNU-stack,"",@progbits

三、汇编

汇编器是将汇编代码转变成机器可以执行的指令,几乎每一条汇编语句都对应一条机器指令。因此汇编过程非常简单。根据汇编指令和机器指令的对照表进行翻译就行了。
gcc -c test.s -o test.o得到二进制.o文件
在这里插入图片描述

四、链接

项目不止一个文件组成,有多个C语言模块,每个模块之间存在函数和变量的访问,那就需要知道模块和函数的地址,因此模块间这种调用关系需要用规定好的符号联系起来,所以这个模块间的拼接过程就是链接过程
在gcc中用gcc test.o -o text.out生成
或者直接gcc test.c -o text.out
在这里插入图片描述


总结

以上就是整个c代码到可执行程序的整个过程!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值