C语言的编译,汇编和链接
很多人在第一次接触到C语言的时候是在windows的集成开发环境中学的。把写好的C语言程序放到开发环境中,点一下编译按钮就会帮你生成编译好的可执行程序,这个过程看似非常简单,但是其背后需要经过很多的步骤。其具体步骤可以分为预编译,编译,汇编,链接四部。
下面我们就在Linux中利用gcc编译器来简单的了解一下一个C文件是如何被编译成一个可执行程序的。
首先我们先来写两个简单的C程序
a.c程序
#include <stdio.h>
#define ADD(a,b) (a + b) // 宏定义
extern int globe_B; // 外部声明b.c中的全局变量
int main(void)
{printf("globe_B = %d\r\n",globe_B); // 打印出globe_B的值printf("ADD(4,5) = %d\r\n",ADD(4,5)); // 打印出,ADD(4,5)的值
}
b.c程序
int globe_B = 50;
上面两个程序很简单,a.c程序只是简单得打印出globe_B的值和打印出ADD宏定义的值。b.c程序只定义一个globe_B的全局变量。
- 预编译
首先来看预编译,预编译的作用是把程序中的宏定义、头文件全部展开、处理条件编译的真假值、去掉注释等作用,最后预编译得到的是一个纯净的C文件。
在gcc中利用gcc -E xxx.c -o xxx.i得到预编译后的文件。
下面来对a.c文件进行预编译
# 1 "a.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "a.c"
# 1 "/usr/include/stdio.h" 1 3 4
# 27 "/usr/include/stdio.h" 3 4
# 1 "/usr/include/features.h" 1 3 4
# 367 "/usr/include/features.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 1 3 4
# 410 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4
# 411 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 2 3 4
# 368 "/usr/include/features.h" 2 3 4
# 391 "/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
# 392 "/usr/include/features.h" 2 3 4
# 28 "/usr/include/stdio.h" 2 3 4/********************省略***********************/extern int globe_B;
int main(void)
{printf("globe_B = %d\r\n",globe_B);printf("ADD(4,5) = %d\r\n",(4 + 5));
}
因为头文件stdio预编译后会展开变成800多行的代码,所以就省略了大部分程序。可以看到a.c被预编译后,注释已经消失了,在第二个printf的ADD宏定义也被展开了,条件编译大家可以自行进行实验。
- 编译
编译是在第一步预编译的基础上,对C文件进行语法和语义检查,排除掉有错误的语句,最后得到的是汇编文件
在gcc中利用gcc -S xxx.i -o xxx.s得到预编译后的文件。
下面对a.i文件进行编译
.file "a.c".section .rodata
.LC0:.string "globe_B = %d\r\n"
.LC1:.string "ADD(4,5) = %d\r\n".text.globl main.type main, @function
main:
.LFB0:.cfi_startprocpushq %rbp.cfi_def_cfa_offset 16.cfi_offset 6, -16movq %rsp, %rbp.cfi_def_cfa_register 6movl globe_B(%rip), %eaxmovl %eax, %esimovl $.LC0, %edimovl $0, %eaxcall printfmovl $9, %esimovl $.LC1, %edimovl $0, %eaxcall printfmovl $0, %eaxpopq %rbp.cfi_def_cfa 7, 8ret.cfi_endproc
.LFE0:.size main, .-main.ident "GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.12) 5.4.0 20160609".section .note.GNU-stack,"",@progbits
汇编得到的是跟机器架构相关的汇编语言。
汇编
汇编的作用是把第二步生成的汇编文件转化成目标文件,也就是二进制文件。
在gcc中用gcc -c xxx.s -o xxx.o生成
由于生成的文件是二进制文件,所以一般的文本工具不能打开,必须要用一些二进制查看软件才可以,常用的有winhex。
上面是用winhex打开的a.o二进制文件。链接
链接是把第三步中生成的所有目标文件全部链接成一个可执行文件。在链接的时候链接器会把各个文件中的函数,变量一一对应,如果某个变量或函数没有做外部声明就会报链接错误。
在gcc中用gcc xxx.o -o xxx.out生成
最后链接出来的可执行文件运行正常。
在实际开发中常用gcc xxx.c -o xxx.out一步到位直接生成可执行文件。
C语言的编译,汇编和链接相关推荐
- c语言编辑编译链接,C语言的“编译、链接”
我们写的代码,仅仅是文本文件(txt),不管后缀怎么变,终究是文本文件,计算机只能显示,不能做事(执行). 文本文件通过"编译.链接",成为可执行文件(windows下是exe): ...
- 易语言静态编译链接器大全(为EIDE助手准备滴)
点击阅读原文 本文中的各个链接器收集于网络,汇总在一起,方便广大易友下载使用: 易语言的大部分支持库是 使用 vc6 编译, 所以, 推荐大家使用 vc6的链接器: 如果使用 其他链接库编译出现问题, ...
- python语言不用编译_python程序不需要编译吗
python编译过程和执行原理 (1)python执行原理 这里的解释执行是相对于编译执行而言的.我们都知道,使用C/C++之类的编译性语言编写的程序,是需要从源文件转换成计算机使用的 机器语言,经过 ...
- 【C 语言】编译过程 分析 ( 预处理 | 编译 | 汇编 | 链接 | 宏定义 | 条件编译 | 编译器指示字 )
相关文章链接 : 1.[嵌入式开发]C语言 指针数组 多维数组 2.[嵌入式开发]C语言 命令行参数 函数指针 gdb调试 3.[嵌入式开发]C语言 结构体相关 的 函数 指针 数组 4.[嵌入式开发 ...
- Linux下C语言执行过程(预处理,编译,汇编,链接,执行)
1.C语言的执行过程包括5个步骤:分别是:预处理,编译,汇编,链接,执行 第一步:编写C源代码,截图如下: 2.预处理,命令为:gcc -E variable.c -o variable.i(这步的作 ...
- C语言的预处理、编译、汇编、链接
2019独角兽企业重金招聘Python工程师标准>>> 一.预处理 预处理指令的执行主要包含下列事情: 1.头文件的包含 2.注释的删除 3.宏定义的替换 4.条件编译的选择 指令: ...
- c语言程序的生命周期(编写、预处理、编译、汇编、链接、执行)
目录 程序的生命周期 一.引言 二.程序经历的六个阶段 1.阶段一:编辑(Edit) 2.程序编译系统(Programs Compilation System) 阶段二:预处理(Preprocess) ...
- C语言 程序的翻译 预处理 编译 汇编 链接 #define详解
1.程序的翻译环境和执行环境 执行环境:所在操作系统的平台 win10 win11 linux 翻译环境:MSVC gcc g++ 你的vs 2019 和2022 是集成开发环境把编辑器编译器全部给你 ...
- c语言编译过程详解,预处理,编译,汇编,链接(干货满满)
楔子 我们在各自的电脑上写下代码,得明白我们代码究竟是如何产生的,不想了解1,0什么的,但这几个环节必须掌握吧. 我们的代码会经过这4个环节,从而形成最终文件,c语言作为编译语言,用来向计算机发出指令 ...
最新文章
- 什么是Unwind segues,您如何使用它们?
- PostgreSQL 务实应用(三/5)分表复制
- 关于sublime-text-2的Package Control组件安装方法,自动和手动
- Android笔记之自定义Editext
- idea中git分支、合并与使用
- 2017android 最强旗舰,2017年世界六大旗舰机,华为第五,第一惊艳全球!
- js 滚动条自动滚动到最底部
- 【报告分享】2020全球网络趋势报告.pdf(附下载链接)
- 如何进阶一名有竞争力的程序员?
- 实验4-1-2 求奇数和 (15 分)
- Python爬虫之(三)urllib库
- js 中 ! + - ~ 符号和匿名函数
- DB9串口定义及含义
- 【Matlab绘图】plot3函数绘制三维点或线图
- Oracle get、start、edit、spool命令,临时变量、已定义变量
- WebApp实时开源框架Clouda入门使用与记录
- 【面试题集 —— No.01】常见图片格式BMP、JPG/JPEG、PNG、GIF、TIFF、SVG的区别
- 开启和关闭远程Windows系统3389端口
- B-010 详细解析电源滤波电容的选取与计算
- 《短线交易秘诀》读后感
热门文章
- Mac照片后期处理软件软件:Capture One 21 Pro
- 学习Figma心得体会
- ASP.NET 调试出现%@ Application Codebehind=Global.asax.cs Inherits=XXX.XXX.Global Language=C# %...
- PHP-为图片再添加水印图片
- 如何理解线程与进程(含有通俗解释)
- setInterval影响性能导致卡死的解决方法
- vue+element制作音乐播放器播放进度条bug(鼠标拖拽slider滑块滑动到指定位置无效)
- Python 实现微信防撤回功能
- Sparse Virtual Texture (虚拟贴图技术)
- vba连接mysql代码_vba 连接数据库代码