您的位置:首页 > 职场人生

程序员的自我修养学习笔记——第二章

2012-04-28 22:24 127 查看
从源文件到可以行文件的过程:

预处理——编译——汇编——链接

第一步

预编译:

$gcc -E hello.c -o hello.i

或者

$cpp hello.c > hello.i

注:‘-E’选项表示只进行预编译;cpp是预编译器

预编译主要处理一‘#’开头的预编译指令:

将所有的"#define"删除,并且展开所有的宏定义

处理所有条件预编译指令

处理"#include",将包含的文件插入到该预编译指令的位置。注意,这个过程是递归进行

删除所有注释

添加行号和文件名标识,以便于调试和编译产生的错误和警告

保留所有"#pragma"指令,编译器需要使用它们

编译:

$gcc -S hello.i -o hello.s

也可以将编译和预编译合并,通过一个gcc提供的程序ccl来完成:

$/usr/lib/gcc/usr/lib/gcc/i686-pc-cygwin/ccl hello.c

或者:

$gcc -S hello.c -o hello.s

实际上gcc这个命令只是一些列后台程序的包装,它会根据不同的参数要求去调用预编译程序ccl、汇编器as、连接器ld。

汇编:是将汇编代码转换为机器码的过程

这样来完成汇编:

$as hello.s -o hello.o

或者:

$gcc -c hello.s -o hello.o

或者:从.c文件开始

$gcc -c hello.c -o hello.o

链接:将.o文件变为可执行文件的过程(这是一个复杂的过程)

需要经过下面的一些命令来完成:

ld -static crt1.o crti.o crtbeginT.o hello.o -start-group -lgcc -lgcc_eh

-lc-end-group crtend.o crtn.o

注:到后面的时候记录一下各个参数的作用,然后在这里补充

编译器都做了什么:

编译过程一般可以分为6步:扫描、语法分析、语义分析、源代码优化、代码生成和目标代码优化。



词法分析:

运用有限状态机(Finite State Machine)可以轻松的将源代码的字符序列分割成一系列的记号。

此法分析产生的记号一般有一下几类:关键字、标识符、字面量(包含数字、字符串等)和特殊符号(如加号、等号)

语法分析:

语法分析器(Grammar Parser)将对由扫描器产生的记号进行语法分析,从而产生语法树。

由语法分析器生成的语法树就是以表达式为节点的树。

语义分析:

编译器所能分析的语义是静态语义,所谓静态语义是指在编译期间可以确定的语义,与之相对应的动态语义,就是在运行期才能确定的语义。

函数访问必须知道目标函数的地址,变量访问也必须知道目标变量的地址,所以这两种方式都可以归结为一种方式,那就是模块间符号的引用。

人们把每个源代码模块独立地编译,然后按照需要将它们组装起来,这个组装模块的过程就是“链接”

链接的主要内容就是把各个模块之间相互引用的部分处理好,使得各个模块之间能够正确衔接。

链接过程主要包括地址和空间分配、符号决议和重定位。

重定位发生在链接阶段,如果一个模块需要使用另一个模块的变量或函数,编译的时候先给这个变量或函数一个特殊的地址,链接的时候再来确定实际地址。这个 地址修正的过程也叫做重定位,每个要被修正地方叫一个重定位入口。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: