您的位置:首页 > 其它

C程序到可执行程序的转换过程

2008-11-06 12:24 169 查看
对于一个C程序而言,要想能够在机器上运行,它需要经历很多步骤。首先,需要Compiler将其转换为汇编语言程序,然后利用Assembler再将其转换为机器语言程序(也就是二进制码),然后应该是利用linker将它和必要的库文件链接在一起。最后才是用loader将连接的文件从磁盘中读到内存中,然后才能被计算机执行,从而产生结果。

对于Compiler是如何转换的可以参见Compiler--Dragon Book. 而Assembler应该比较简单,它主要就是将符号语言对应到机器码而已。经过Assembler处理后的文件分为以下几个部分:一些统计信息(如包含的过程名,text size, data size),text segment, data segment, relocation info, symbol table。统计信息的作用是在linker的时候很容易计算应该分配给text以及data的内存的大小。text segment也就是code。data setment应该是static variables区域吧。而relocation info记录的是当前object file中还不知道地址的code或data的地址。symbol table记录的是文件中的每个label以及其地址的对应。这里的label可以是code也可以是data。而Linker的作用就是根据object files中的信息将多个object files进行组合成为一个整体,这里他的主要任务是解决还不知道具体位置的lable的地址,主要通过object files中记录的信息。而Loader的作用就是将最后的可执行文件放入内存,并设置相应的机器状态,以便执行程序。

对于Linker,有一个dynamically linked libraries的概念。普通的Linker是将所有的库文件以及原object files全部连在一起,当然这是在程序执行之前。这样做的话一方面会使可执行文件不能适应变化,比如当libraries进行了改进后,原有的可执行文件就必须重新连接一边。另外在用户文件中并不会用到libraries中的所有库函数,如果将所有引用的库全组合在一起的话,必然会不必要的增加可执行文件的长度。而dynamically linked libraries技术就是为了解决这个问题的。他用到的主要思想就是indirection。也就是说在用户文件中对所有库文件的调用都首先转到一个dummy routines。当然这些routines是和原文件静态链接的。每一个库函数都对应有一个dummy routine。这些dummy routines首先会将一个特定的数字放入特定的register中,这个数字对应于该dummy routine所对应的库函数。然后这些dummy routine会调用一个dynamic linker-loader。这个linker-loader根据前面的数字从dll文件中找到对应的函数并将其加入到内存中。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: