编译和链接(翻译环境:预编译+编译+汇编+链接​、运行环境)

这篇具有很好参考价值的文章主要介绍了编译和链接(翻译环境:预编译+编译+汇编+链接​、运行环境)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、翻译环境和运行环境​

在ANSI C的任何一种实现中,存在两个不同的环境。​
第1种是翻译环境,在这个环境中源代码被转换为可执行的机器指令。​
第2种是执行环境,它用于实际执行代码。​

编译和链接(翻译环境:预编译+编译+汇编+链接​、运行环境),汇编,c语言,c++,开发语言,笔记

编译和链接(翻译环境:预编译+编译+汇编+链接​、运行环境),汇编,c语言,c++,开发语言,笔记编译和链接(翻译环境:预编译+编译+汇编+链接​、运行环境),汇编,c语言,c++,开发语言,笔记

VS中编译器:cl.exe ;Linux中目标文件后缀.o 

Windows中目标文件.obj  ,链接器 link.exe

翻译环境​

那翻译环境是怎么将源代码转换为可执行的机器指令的呢?这里我们就得展开开讲解一下翻译环境所做的事情。
其实翻译环境是由编译和链接两个大的过程组成的,而编译又可以分解成:预处理(有些书也叫预编译)、编译、汇编三个过程。

  • 一个C语言的项目中可能有多个 .c 文件一起构建,那多个 .c 文件如何生成可执行程序呢?​
  • 多个.c文件单独经过编译出编译处理生产对应的目标文件。​
  •  注:在Windows环境下的目标文件的后缀是 .obj ,Linux环境下目标文件的后缀是 .o ​
  • 多个目标文件和链接库一起经过链接器处理生成最终的可执行程序。
  • 链接库是指运行时库(它是支持程序运行的基本函数集合)或者第三方库。

编译和链接(翻译环境:预编译+编译+汇编+链接​、运行环境),汇编,c语言,c++,开发语言,笔记

VS2022  IDE 集成开发环境

Linux 环境下C语言编译器:gcc

二、预处理(预编译)​

在预处理阶段,源文件和头文件会被处理成为.i为后缀的文件。​
在 gcc 环境下想观察一下,对 test.c 文件预处理后的.i文件,命令如下:​

gcc -E test.c -o test.i

test.c文件进行预处理,并将预处理后的结果输出到test.i文件中

编译和链接(翻译环境:预编译+编译+汇编+链接​、运行环境),汇编,c语言,c++,开发语言,笔记

预处理阶段主要处理那些源文件中#开始的预编译指令。比如:#include,#define,处理的规则如下:​
• 将所有的 #define 删除,并展开所有的宏定义。​
• 处理所有的条件编译指令,如: #if、#ifdef、#elif、#else、#endif 。
• 处理#include 预编译指令,将包含的头文件的内容插入到该预编译指令的位置。这个过程是递归进行的,也就是说被包含的头文件也可能包含其他文件。
• 删除所有的注释
• 添加行号和文件名标识,方便后续编译器生成调试信息等。
• 或保留所有的#pragma的编译器指令,编译器后续会使用。​
经过预处理后的.i文件中不再包含宏定义,因为宏已经被展开。并且包含的头文件都被插入到.i文件
中。所以当我们无法知道宏定义或者头文件是否包含正确的时候,可以查看预处理后的.i文件来确认。

三、编译​

编译过程就是将预处理后的文件进行一系列的:词法分析、语法分析、语义分析及优化,生成相应的汇编代码文件。
编译过程的命令如下:

gcc -S test.i -o test.s

预处理后的test.i文件编译成汇编代码,并将结果输出到test.s文件中

对下面代码进行编译的时候,会怎么做呢?假设有下面的代码

array[index] = (index+4)*(2+6);

3.1词法分析:​

将源代码程序被输入扫描器,扫描器的任务就是简单的进行词法分析,把代码中的字符分割成一系列的记号(关键字、标识符、字面量、特殊字符等)。
上面程序进行词法分析后得到了16个记号

编译和链接(翻译环境:预编译+编译+汇编+链接​、运行环境),汇编,c语言,c++,开发语言,笔记

3.2语法分析​

接下来语法分析器,将对扫描产生的记号进行语法分析,从而产生语法树。这些语法树是以表达式为节点的树。

编译和链接(翻译环境:预编译+编译+汇编+链接​、运行环境),汇编,c语言,c++,开发语言,笔记

四、汇编

汇编器是将汇编代码转转变成机器可执行的指令,每一个汇编语句几乎都对应一条机器指令。就是根据汇编指令和机器指令的对照表一一的进行翻译,也不做指令优化。
汇编的命令如下:

gcc -c test.s -o test.o

五、链接​

链接是一个复杂的过程,链接的时候需要把一堆文件链接在一起才生成可执行程序。
链接过程主要包括:地址和空间分配,符号决议和重定位等这些步骤。
链接解决的是一个项目中多文件、多模块之间互相调用的问题。
比如:
在一个C的项目中有2个.c文件( test.c 和 add.c ),代码如下:​
编译和链接(翻译环境:预编译+编译+汇编+链接​、运行环境),汇编,c语言,c++,开发语言,笔记

编译和链接(翻译环境:预编译+编译+汇编+链接​、运行环境),汇编,c语言,c++,开发语言,笔记

我们已经知道,每个源文件都是单独经过编译器处理生成对应的目标文件。
test.c 经过编译器处理生成 test.o ​
add.c 经过编译器处理生成 add.o ​

我们在 test.c 的文件中使用了 add.c 文件中的 Add 函数和 g_val 变量。
我们在 test.c 文件中每一次使用 Add 函数和 g_val 的时候必须确切的知道 Add 和 g_val 的地
址,但是由于每个文件是单独编译的,在编译器编译 test.c 的时候并不知道 Add 函数和 g_val变量的地址,所以暂时把调用 Add 的指令的目标地址和 g_val 的地址搁置。等待最后链接的时候由链接器根据引用的符号 Add 在其他模块中查找 Add 函数的地址,然后将 test.c 中所有引用到Add 的指令重新修正,让他们的目标地址为真正的 Add 函数的地址,对于全局变量 g_val 也是类似的方法来修正地址。这个地址修正的过程也被叫做:重定位。

前面我们非常简洁的讲解了一个C的程序是如何编译和链接,到最终生成可执行程序的过程,其实很多内部的细节无法展开讲解。比如:目标文件的格式elf,链接底层实现中的空间与地址分配,符号解析和重定位等,如果你有兴趣,可以看《程序的自我修养》一书来详细了解。

六、运行环境​

  1.  程序必须载入内存中。在有操作系统的环境中:一般这个由操作系统完成。在独立的环境中,程序的载入必须由手工安排,也可能是通过可执行代码置入只读内存来完成。
  2.  程序的执行便开始。接着便调用main函数。​
  3.  开始执行程序代码。这个时候程序将使用一个运行时堆栈(stack),存储函数的局部变量和返回地址。程序同时也可以使用静态(static)内存,存储于静态内存中的变量在程序的整个执行过程一直保留他们的值。
  4.  终止程序。正常终止main函数;也有可能是意外终止。​

编译和链接(翻译环境:预编译+编译+汇编+链接​、运行环境),汇编,c语言,c++,开发语言,笔记

编译和链接(翻译环境:预编译+编译+汇编+链接​、运行环境),汇编,c语言,c++,开发语言,笔记

七、预定义符号​

C语言设置了一些预定义符号,可以直接使用,预定义符号也是在预处理期间处理的。​

__FILE__ //进行编译的源文件​
__LINE__ //文件当前的行号​
__DATE__ //文件被编译的日期​
__TIME__ //文件被编译的时间​
__STDC__ //如果编译器遵循ANSI C,其值为1,否则未定义​

举个例子:

printf("file:%s line:%d\n", __FILE__, __LINE__);

int main()
{
   printf("%s\n", __FILE__);
	printf("%s\n", __DATE__);
	printf("%s\n", __TIME__);
   //printf("%d\n", __STDC__);//gcc是支持ANSI C的

    return 0;
}

编译和链接(翻译环境:预编译+编译+汇编+链接​、运行环境),汇编,c语言,c++,开发语言,笔记

今天就先到这了!!!

编译和链接(翻译环境:预编译+编译+汇编+链接​、运行环境),汇编,c语言,c++,开发语言,笔记

看到这里了还不给博主扣个:
⛳️ 点赞☀️收藏 ⭐️ 关注!

你们的点赞就是博主更新最大的动力!
有问题可以评论或者私信呢秒回哦。文章来源地址https://www.toymoban.com/news/detail-819177.html

到了这里,关于编译和链接(翻译环境:预编译+编译+汇编+链接​、运行环境)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • GCC编译过程:预处理->编译->汇编->链接

    GCC编译过程:预处理->编译->汇编->链接

    目录 引言  概括介绍 一、预处理 二、编译 三、汇编 四、链接 总结 当使用集成开发环境(IDE)进行C语言编程时,点击\\\" 编译 \\\"按钮后,整个C程序从源代码到可执行文件的生成过程会自动完成。IDE会在后台为我们执行C语言的编译过程,将源代码转换为最终的可执行文件。虽

    2024年02月13日
    浏览(12)
  • 【编译、链接、装载十六】汇编与指针、汇编与new

    简介:我们从预处理、编译、汇编、编译、链接、装载一路走到现在,一直在c语言的层面分析,原因还是这些知识太苦涩,理解时需要看下具体的反汇编代码,且c++的反汇编更难理解些,所以,c语言的入手比c++入手更简单和更好理解些。在这个系列的结尾,我们从汇编层面

    2024年02月13日
    浏览(7)
  • 程序环境和预处理(含C语言程序的编译+链接)--2

    程序环境和预处理(含C语言程序的编译+链接)--2

    文章前言: 上章我们把      程序的翻译环境     程序的执行环境   C语言程序的编译+链接     预定义符号介绍    预处理指令   #define    宏和函数的对比     预处理操作符    #和##的介绍   的相关知识进行了梳理讲解,接下来被把剩余知识    命令定义     预处

    2024年02月14日
    浏览(15)
  • Linux的编译器——gcc/g++(预处理、编译、汇编、链接)

    Linux的编译器——gcc/g++(预处理、编译、汇编、链接)

    前言: 本文主要认识与学习 Linux 环境下常用的编译器—— gcc (编译 C 代码)/ g++ (编译 C++ 代码)的常用指令等、程序实现的两大环境、动态库与静态库的理解等。 任何一个 C 程序的实现都要经过 翻译环境 与 执行环境 。 在翻译环境中又分为4个部分, 预编译、编译、汇

    2024年02月13日
    浏览(11)
  • Keil MDK配置ARM汇编/C语言混合开发环境

    Keil MDK配置ARM汇编/C语言混合开发环境

    1. 安装Keil MDK 安装方法这里不再说明,懂得都懂!🐶 2. 安装ARM开发包 在Keil MDK5之后,不再原生支持ARM7/9,需要自行安装软件包,链接在这,注意安装与自己MDK版本对应的那个包 我的版本是5.18,下载之后傻瓜式安装,因为它会自动检测你MDK所在的位置。 3. 新建工程 注意:选

    2024年02月02日
    浏览(12)
  • 015+limou+C语言深入知识——(7)编译环境和运行环境以及预处理指令

    015+limou+C语言深入知识——(7)编译环境和运行环境以及预处理指令

    在这个环境中,源代码被转化为可执行的机器指令(二进制指令) 单文件简易版本 多文件简易版本 编译链接详细版本 VS2022集成IDE(windows下)的编译器叫cl.exe,链接器叫link.exe gcc编译器(windows下)的几个有关编译环境的命令 (1)符号表会把全局变量和具有外部链接的函数

    2023年04月11日
    浏览(11)
  • 64位AT&T汇编语言学习第一课:汇编和链接

    64位AT&T汇编语言学习第一课:汇编和链接

    源文件 exitTest.s 内容如下: 源文件里边放的就是源代码,而我这里源代码是使用汇编语言写的,都是一些人类都可以阅读的字符。之后需要经过汇编器的汇编,变成目标文件(里边存放的是机器语言)。我这里使用的汇编器是GAS汇编器,命令是 as ,命令格式是 as 源文件名

    2024年01月17日
    浏览(17)
  • 64位AT&T汇编语言as汇编ld链接,执行报错Segmentation fault

    64位AT&T汇编语言as汇编ld链接,执行报错Segmentation fault

    absCallAndPrintAbsAsLd.s 里边的内容如下: as -g absCallAndPrintAbsAsLd.s -o absCallAndPrintAbsAsLd.o 进行汇编。 ld -g absCallAndPrintAbsAsLd.o -o absCallAndPrintAbsAsLd -lc -I /usr/lib64/ld-linux-x86-64.so.2 进行链接。 ./absCallAndPrintAbsAsLd 执行报错 Segmentation fault 。 我把 rsp 中的地址加上8之后,就不报错了,因为这

    2024年01月24日
    浏览(13)
  • 嵌入式C语言自我修养笔记1-ARM体系结构与编译运行

    嵌入式C语言自我修养笔记1-ARM体系结构与编译运行

    ARM 体系结构 ARM 体系结构 ARM 相对精简指令集 RISC 还有如下区别 ● ARM 有桶型移位寄存器,单周期内可以完成数据的各种移位操作。 ● 并不是所有的 ARM 指令都是单周期的。 ● ARM 有 16 位的 Thumb 指令集,是 32 位 ARM 指令集的压缩形式,提高了代码密度 ● 条件执行:通过指令

    2024年02月07日
    浏览(49)
  • Windows Java JavaFX IntelliJ IDEA 开发环境搭建 创建工程 编译运行 打包分发 自定义运行时

    Windows Java JavaFX IntelliJ IDEA 开发环境搭建 创建工程 编译运行 打包分发 自定义运行时

    博文目录 JavaFX 官网 官网 Getting Started with JavaFX JavaFX 是一个开源的下一代客户端应用程序平台,适用于基于 Java 构建的桌面、移动和嵌入式系统。它是许多个人和公司的协作成果,目标是为开发富客户端应用程序生成一个现代、高效且功能齐全的工具包。 JavaFX 主要致力于富

    2024年02月05日
    浏览(15)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包