2013-05-06 链接

来源:互联网 发布:布料模拟 算法 编辑:程序博客网 时间:2024/05/06 19:29

  据上次写博客已经过了十多天了,中间加上五一放假和工作中程序出了点问题,导致一直没有时间来继续写,今天继续,今天的主题是链接


链接

链接是将各种代码和数据部分收集起来并组合成一个单一文件的过程,这个文件可被加载到存储器并执行。

一个程序的编译过程分为:预编译、编译、汇编和链接

链接过程中需要解决的问题有两个:1、符号解析  2、重定位

一、符号解析

说到符号解析,就不能不说符号和符号表了

在链接器的上下文中,有三种不同的符号:

1、有m定义且能被其他模块引用的全局符号,全局链接器对应于非静态的C函数以为被定义为不带C static属性的全局变量

2、由其他模块定义并被模块m引用的全局符号,这些符号成为外部符号

3、由m定义和引用的本地符号,这些符号不能被其他模块引用

编译器对于多重定义的符号解析是通过一种称为强弱符号的概念

强符号:函数和已初始化的全局变量

若符号:未初始化的全局变量

那么编译器是如何解析多重定义的符号呢?有以下规则

规则1:不允许有多个强符号

规则2:如果有一个强符号和多个弱符号,那么选择强符号

规则3:如果有多个弱符号,那么就随机选择一个


二、重定位

一般的.O文件中对于变量的位置,如果是从其他文件中导入的,在.O文件中,一般通过对地址0的偏移量来表示的,但是当程序需要运行的时候,这个偏移量显然不能代表当前参数的实际的值,所以就需要通过重定位来确定这个参数实际的地址,

 至于如何重定位,重定位后的地址是如何确认了,这里就不多说了,简单来说,这个地址确认是通过一个公式计算来的,

以后会为大家详解这里。


程序是如何运行的:

看下面这段代码:

call __libc_init_first

call _init

call atexit

call main

call _exit

这里面前两个函数就是程序运行开始之前初始化的东西,包括创建程序自己的虚拟存储器等等

call atexit  , atexit这个程序附加了一系列在应用程序正常终止时应该调用的程序,

call main  这条语句为我们解释了为什么所有的C语言程序都需要一个main函数   这段代码是C语言的启动代码,这段代码表明,启动代码需要跳转到一个叫做main函数中

call _exit  程序执行完,通过调用_exit函数将控制返回给操作系统


这里简单介绍编译链接的基础,让大家对编译链接有个基本的印象,以后会慢慢一点一点拨开编译链接的秘密,将整个过程一点一点的展现在大家面前




原创粉丝点击