程序环境——翻译环境与执行环境

本篇重点:

1.程序的翻译环境和执行环境

2.详解翻译环境中的 编译+链接


----------------------------------------------------------------------------------------------------------------------


程序的翻译环境和执行环境

在ANSI的任何一种实现中,存在两个不同的环境。

1. 翻译环境,在这个环境中源代码被转换为可执行的机器指令。

2. 执行环境,它用于实际执行代码。


翻译环境


^ 组成一个程序的每个源文件通过编译过程分别转换成目标文件(object code)

^ 每个目标文件由链接器(linker)捆绑在一起,形成一个单一而完整的可执行程序(.exe)。

^ 链接器同时也会引入标准C函数库中任何被该程序所用到的函数,而且它可以搜索程序员个人的程序库,将其需要的函数也链接到程序中。



编译+链接

我们把翻译环境分为两个部分,分别是编译链接。而编译部分又可分为三个部分,分别是预编译编译汇编


接下来我们就分别来看看这几个阶段。(Linux操作系统下演示)


预处理   (gcc test.c -E > test.i)

看这段代码:


经过预处理后变成了这样:


本来只有几行的代码变成了几百行,是哪里变了呢?

1. #include包含的函数stdio.h显示出来了。

2. 注释被删除了。 

3. #include符号替换了。  

这些就是预编译阶段所完成的内容。 


编译       (gcc test.i -S)

经过编译之后,代码已经成这样了:


已经把C语言代码转换为汇编代码。

在转换的过程中还要经历下面这几个内容: 

1.语法分析:

若是源代码写成这样 #define MAX = 100,那么编译时会报错,报错如下


2.词法分析:判断源程序中单词符号的合法性。

3.语义分析:检测例如类似于for循环有没有使用错误。

4.符号汇总:(本例)g_val  Add  main 。  (后面来介绍符号汇总有什么用)


汇编     (gcc test.s -c)

把汇编代码转换成机器指令。

转换过程中的内容:

形成符号表(readelf test.o -s):给每个汇总的符号一个地址。


链接

我们把源文件中的Add函数改成extern int Add(int x, int y),然后再创建一个新的源文件sum.c,内容如下图,汇编后,Add会有一个地址。 



我们假设   sum.c中  Add地址是  0x100

                 test.c中  Add             0x000 (无意义地址)

                               g_val           0x200

                              main            0x300

                              printf           0x400

每个目标文件由链接器捆绑在一起,形成一个单一而完整的可执行程序。所以Add也将合并在一起,用有效的地址。即


所以链接过程中主要的操作有以下两点:

1.符号表的合并和重定位。

2.合并段表。


以上就是翻译环境的主要内容,为了方便记忆,给大家一幅图来帮助记忆。

        


执行环境

程序执行的过程:

1. 程序必须载入内存中。在有操作系统的环境中:一般这个有操作系统完成。在独立的环境中,程序的载入必须由手工安排,也可能是通过可执行代码置入只读内存来完成。

2. 程序的执行开始。接着便调用main函数。

3. 开始执行程序代码。这个时候程序将使用一个运行时堆栈(stack),存储函数的局部变量和返回地址。程序同时也可以使用静态(static)内存,存储在静态内存中的变量在程序的整个执行过程一直保留他们的值。

4. 终止程序。正常终止main函数;也有可能是意外终止。


----------------------------------------------------------------------------------------------------------------------


以上就是程序环境:翻译环境与执行环境的全部内容了,你学会了吗?





猜你喜欢

转载自blog.csdn.net/hyb_91/article/details/80320004