程序员的自我修养学习笔记——第二章
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)将对由扫描器产生的记号进行语法分析,从而产生语法树。
由语法分析器生成的语法树就是以表达式为节点的树。
语义分析:
编译器所能分析的语义是静态语义,所谓静态语义是指在编译期间可以确定的语义,与之相对应的动态语义,就是在运行期才能确定的语义。
函数访问必须知道目标函数的地址,变量访问也必须知道目标变量的地址,所以这两种方式都可以归结为一种方式,那就是模块间符号的引用。
人们把每个源代码模块独立地编译,然后按照需要将它们组装起来,这个组装模块的过程就是“链接”
链接的主要内容就是把各个模块之间相互引用的部分处理好,使得各个模块之间能够正确衔接。
链接过程主要包括地址和空间分配、符号决议和重定位。
重定位发生在链接阶段,如果一个模块需要使用另一个模块的变量或函数,编译的时候先给这个变量或函数一个特殊的地址,链接的时候再来确定实际地址。这个 地址修正的过程也叫做重定位,每个要被修正地方叫一个重定位入口。
预处理——编译——汇编——链接
第一步
预编译:
$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)将对由扫描器产生的记号进行语法分析,从而产生语法树。
由语法分析器生成的语法树就是以表达式为节点的树。
语义分析:
编译器所能分析的语义是静态语义,所谓静态语义是指在编译期间可以确定的语义,与之相对应的动态语义,就是在运行期才能确定的语义。
函数访问必须知道目标函数的地址,变量访问也必须知道目标变量的地址,所以这两种方式都可以归结为一种方式,那就是模块间符号的引用。
人们把每个源代码模块独立地编译,然后按照需要将它们组装起来,这个组装模块的过程就是“链接”
链接的主要内容就是把各个模块之间相互引用的部分处理好,使得各个模块之间能够正确衔接。
链接过程主要包括地址和空间分配、符号决议和重定位。
重定位发生在链接阶段,如果一个模块需要使用另一个模块的变量或函数,编译的时候先给这个变量或函数一个特殊的地址,链接的时候再来确定实际地址。这个 地址修正的过程也叫做重定位,每个要被修正地方叫一个重定位入口。
相关文章推荐
- 结合《第二章 C语言的基本元素》课程和网络,对以下每个问题发表感慨
- 第二章 java基础(数组下标)
- TCP/IP详解--第二章
- 第二章
- VRML---第二章(几何造型节点)
- 《Spring揭秘》第二章 读书笔记 —— IoC的基本概念
- 踏入PL/SQL大门的第一步之SQLPLUS 学习(第二章)
- Kali Linux Web 渗透测试秘籍 第二章 侦查
- Linux内核设计与实现笔记之第一章、第二章
- 深度学习笔记(二)第二章 线性代数
- 第二章、 Linux 如何学习
- python(第二版)第二章答案
- 第二章 jQuery技术解密 (七)
- 【golang 源码分析】第二章 RPC client源码分析
- 第二章 Libgdx的目标和特性
- KVM虚拟化实战精讲[第二章 安装KVM]
- 第二章_算法分析
- 读《图解HTTP》总结--第二章
- Windows核心编程 第二章 字符和字符串处理
- 微机原理==第二章16位和32位微处理器(5)