C语言程序的翻译环境和执行环境

 

目录

一、概述:翻译环境、执行环境

1.翻译环境

2.执行环境(运行环境)

二、详述翻译环境——编译环境、链接环境

1.编译环境

2.链接环境

三、详述编译过程——预编译、编译、汇编

1.预编译(预处理)

2.编译(Linux环境下测试)

编译器如何将C语言代码翻译成汇编代码?

(1)词法分析

(2)语法分析

(3)语义分析

(4)符号汇总

3.汇编(Linux环境下测试)

汇编器如何将汇编代码翻译成二进制指令?

(1)生成符号表

四、详述链接过程——合并段表、符号表的合并与重定位

1.合并段表

2.符号表的合并与重定位


一、概述:翻译环境、执行环境

在ANSI C(标准C语言)的任何一种实现中,都存在两种环境:

1.翻译环境

在这个环境中,源代码被转换为可执行的二进制指令

在一个项目工程中,test.c就是源文件(源代码),可以在存放该项目工程的文件夹中找到该源文件。该源文件存放的是文本信息代码,可以直接用记事本打开,可以看到源代码

C语言程序的翻译环境和执行环境_第1张图片

这样的源代码并不能直接运行,而是要通过翻译环境形成一个可执行程序text.exe,该可执行程序中存放的是二进制指令(机器指令)。同样也可以用记事本打开,但是打开后看到的是一堆乱码,因为存放的都是二进制的信息,记事本打开无法查看。

C语言程序的翻译环境和执行环境_第2张图片

2.执行环境(运行环境)

用于实际执行代码(执行二进制指令)

当源文件test.c通过翻译环境产生可执行文件test.exe后,该可执行文件就可以通过执行环境执行,最终得到执行结果。

二、详述翻译环境——编译环境、链接环境

在翻译环境下,又分为两个环境:编译环境和链接环境

1.编译环境

源文件test.c通过编译器生成目标文件test.obj(Linux环境下的目标文件时test.o),该目标文件中存放的是二进制指令,用记事本打开同样是一堆乱码。

(VS2022环境下的编译器是cl.exe)

C语言程序的翻译环境和执行环境_第3张图片

如果有多个源文件,那么这些源文件都要单独通过编译器生成对应的目标文件

C语言程序的翻译环境和执行环境_第4张图片

2.链接环境

所有目标文件和链接库经过链接器的处理最终生成一个可执行文件test.exe

(VS2022环境下的链接器是link.exe)

链接库:是Windows系统中封装代码和数据以及实现资源共享的一种方式,本质上是已经编译好的二进制指令文件(机器指令文件)

例如包含头文件时使用的C语言标准库就是以链接库的形式和其他目标文件通过链接器链接

C语言程序的翻译环境和执行环境_第5张图片

三、详述编译过程——预编译、编译、汇编

编译器对源文件进行编译的具体过程分为3步:预编译(预处理)、编译、汇编

1.预编译(预处理)

预编译时,编译器会进行以下动作:

1.将所有的注释替换为空格

2.将#define定义的标识符(宏)替换为对应的常量或函数(宏展开)

3.将包含的头文件中所有的内容以及源文件代码整合并生成一个test.i文件

(预处理后得到的test.i文件仍然是C语言代码)

VS2022环境下,将编译器设置改为预处理到文件,这样编译器会将预处理完成后的结果放到test.i文件。相比于源文件,该test.i文件末尾代码是进行了注释替换和宏展开的源代码,上面还有一万多行代码是将头文件所包含的所有内容。

C语言程序的翻译环境和执行环境_第6张图片

C语言程序的翻译环境和执行环境_第7张图片

C语言程序的翻译环境和执行环境_第8张图片

2.编译(Linux环境下测试)

将test.i文件的C语言代码翻译成汇编代码,存放到test.s文件中

C语言程序的翻译环境和执行环境_第9张图片

编译器如何将C语言代码翻译成汇编代码?
(1)词法分析

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

例如下面代码,代码中的字符可被分割成一系列的记号:

C语言程序的翻译环境和执行环境_第10张图片

(2)语法分析

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

C语言程序的翻译环境和执行环境_第11张图片

(3)语义分析

主要是检查是否结构正确的句子所表示的意思也合法、执行规定的语义动作(如:表达式求值、符号表填写、中间代码生成等)

(4)符号汇总

将所有源文件的全局符号汇总起来,包括全局变量名、全局函数名、main。(因为只有全局的函数、变量才涉及到跨文件使用)

3.汇编(Linux环境下测试)

将test.s汇编代码通过汇编器翻译为二进制指令,存放到test.o目标文件中(Windows环境下的目标文件为test.obj)

C语言程序的翻译环境和执行环境_第12张图片

 

汇编器如何将汇编代码翻译成二进制指令?
(1)生成符号表

每个源文件都有自己的符号,汇编器会将源文件各自的符号列成一个表,并为每个符号给予地址。

例如,在下列项目中,有两个源文件 add.c 和 test.c ,汇编器在各自目标文件(.obj)中文件中生成符号表

C语言程序的翻译环境和执行环境_第13张图片

add.obj

test.obj

四、详述链接过程——合并段表、符号表的合并与重定位

1.合并段表

在gcc编译器(Linux环境)中,所有生成的目标文件和二进制文件都是按照 elf 文件格式组织的。将所有的目标文件或二进制文件分成不同的段,每个段存放不同的数据。

C语言程序的翻译环境和执行环境_第14张图片

合并段表就是将这些目标文件和二进制文件相同的段进行合并,生成二进制可执行文件

C语言程序的翻译环境和执行环境_第15张图片

2.符号表的合并与重定位

每个目标文件都有自己的符号表,需要将这些符号表进行合并

最终去查找函数的时候,只需要通过这个合并的符号表根据各符号的地址去查找即可

C语言程序的翻译环境和执行环境_第16张图片

 

正是因为符号表合并的存在,才可以进行函数等的跨文件调用。

如果程序运行时出现了未定义的外部符号报错,说明源文件中并未定义该符号。根据地址查找该符号时,找不到该符号的定义。

你可能感兴趣的:(C/C++,c语言,开发语言,c++,汇编)