日期:2014-05-16  浏览次数:20667 次

关于linux程序在内存中的分布管理

?

?

?

?

这段时间,一直在看汇编,想学习一下linux内核,但是看着看着,感觉汇编操作底层,虽然能力很大,但是不好管理。假如有这个代码 mov ax, [msg+1234h]-->把ds*16+msg+1234h内存里面的东西移动到ax寄存器中,msg表示这段程序的起始地址,但是当我们把这个程序编译连接好后,那么这段代码可能是 mov ax, [2234h]。当我们把这段代码整体平移到0000h起始的地方,这段代码能一定执行吗,不一定吧,有可能报错的。

?

?

比如,把二进制代码从紫色部位,移动到绿色部位,移动后这个代码可能不worK的。因为你的本意是移动相对那个位置的内存内容到AX寄存器中,(比如紫色从左往右数的第2个到AX中)但是编译连接,整体移动后,你却还是移动那个位置的内容(正确的是移动绿色第2个),那怎么解决这个问题呢?

?

这就是连接器的作用了,比如现在有3个程序片段,编译之后都是编号地址都是随机分布的,或相交,或分离。(这里可能说的不正确,只是打个比方)。但是连接的作用就不同了,连接器会分析,分析的范围是整体的。比如你要链接1,2,3三个片段,那么他们的链接效果如下:

?

?

连接器会把三个文件作一个整体性的排序(或者安排吧),实地址替换里面的符号。

?

如果只链接两个呢,那么可能结果如下。

?

?

或者是这样

?

当然了,这只是我的猜测,不一定正确。

?

再说说多道程序,现在有三个程序,从头到尾都是汇编编写,每个程序有若干片段,如果三个程序都链接好了之后,那么假设他们都从地址0h开始加载,那不就又冲突了吗,实模式可没有那么好的内存管理啊。这好像就是保护模式了。

?

如图:

?

有三个程序,每个程序执行的时候,会给每个程序一个选择子,来选择一段内存,加入都从0h地址开始执行,但是A程序是0h,B 程序是10000H开始,C是20000H开始,即使A,B,C的汇编代码一样,但是进入保护模式,CPU会根据每个程序用一种特殊的方法来寻址。(当然这些分段内存是足够大的),这样这些程序加载就不会冲突了,也保证能够正确执行。这些对实模式的汇编指令都是透明的,开启一个开关,寻址的空间发生了变化,这些指令全然不知,呵呵

?

当然,这些都是我的猜测。

?

?

?

?