还是不太明白用Section 汇编后有什么不同。nasm文档只是对伪指令 section 做了这样的解释。不太明白汇编后的文件和内存分配是怎样进行的。
1.如果说内存分配是随机的(执行的时候才被分配内存)
这样汇编出来的东西也是可以在dos这样的操作系统执行(内存分配应该是由OS完成的)。汇编中每出现一个段的定义就是在告诉操作系统现在的这个代码可以给我重新分配一个段,而不需要连续的空间。当汇编程序中只有一个段时,生成的这些代码必须都在一个连续的内存空间中;如果有2个段或多个段,则该程序需要的内存空间可以(我觉得应该是可以,而不是一定)由2个或多个不连续的内存空间组成,这样可以充分利用内存。以上这些都能得到合理的解释,但此时有了一个问题:
操作系统的底层代码就是由汇编写的,也就是说在用汇编写程序的时候,没有操作系统为其分配内存,那么这些段的定义不是就没有用了吗?
2. 如果说不是随机的,每次都是从00000h开始
那么偌大的内存就只能允许一个汇编程序了(大家都是从00000h开始,造成了冲突)。
那么反汇编得到的那些编号都是从00000开始的又是怎么回事? 是相对位置吗?
我想不通的问题就在于:第一个程序似乎已经确定整个汇编出来的东西每次都会被加载到内存的最开始00000h处开始执行。它是怎么做到的?
------解决方案--------------------------------------------------------
//我想不通的问题就在于:第一个程序似乎已经确定整个汇编出来的
//东西每次都会被加载到内存的最开始00000h处开始执行。
//它是怎么做到的?
在windows中某些连接器连接obj时有一个选项可以用来确定进程的加载地址,
比如vc link 的 /base 选项,因为进程空间地址是各个进程独享的,所以
可以在每次加载时保持相同。
------解决方案--------------------------------------------------------
自己动手写操作系统??你在讲笑话呢。
系统加载是这样的,Bootloader跟要被加载的程序,比如操作系统,之间是有约定的,什么样的数据加载到什么样的地址,不是随便设置的。这种约定可以是规定加载地址就在某个地址,或者是被加载文件中本身还有这样的信息,比如ELF格式的文件,本身就有entrypoint决定了加载地址。而Bootloader怎么被加载又是硬件和Bootloader之间的约定规定的,如PPC E500规定CPU执行的第一条指令的位置是0xFFFF FFFC,这个是规定好的。至于文件是怎么生成的,你要看链接器的手册了。如GNU的ld.
------解决方案--------------------------------------------------------
楼上......EntryPoint只指定执行点,装载地址是由program header里面的属性值决定的。
楼主......不同的文件格式,支持不同的“内存地址分配”
比如说通常的可执行程序,它的段只能加载到固定的位置,这个位置是写在ELF文件的program header里面;PE文件好像是固定装载到0x30000000吧,记不清了,可以去查一下关于PE文件格式的文档。
而DLL程序(在linux下面也叫share object ELF文件),它的位置是可变的。在ELF或者PE文件里面,会记录一个“最佳装载”地址,当操作系统检测到这个地址“不可用”时,可以自由的将其移动到其它地址。
这两种文件格式之间,最关键的区别在于--重定位。
在汇编语言里面,“变量名”的本质其实是一个内存地址,也就是说,jmp [标号]在编译之后,实际上就变成了jmp [某地址]
这就对程序的“可移动性”产生了影响。因为在程序被移动以后,这个“某地址”就会被改变,然后就会jmp到一个错误的地址,引起程序崩溃。
为了解决这个问题,我们引入了“重定位”的概念。
我们不再是jmp [某地址],而是jmp [.text段起始+某偏移]--这样一来,无论.text段被移动到任何位置,这个jmp都会跳转到正确的地址。
重定位有两种实现方式,它们都有一定的“副作用”,所以正常的程序会采用“不可重定位格式”,而DLL由于无法装载到固定地址(多个DLL之间会引起冲突),所以DLL都是采用“可重定位格式”的,为了减少重定位带来的损失,DLL文件中通常会给出一个“最佳装载地址”,当装载到这个地址时,不需要进行重定位。
------解决方案--------------------------------------------------------
那么汇编出来的一个连续的文件如果有段标记(或者是masm下的segemnt或是nasm中的section)那么生成的一个文件执行的时候就可以被分到不同的段中,而不一定再保持地址连续。不知道我这样理解对不对。
-----------------------------------------
可以的。
但是对于可执行文件来说,如何拆分,拆分后各个段的相对地址必须在链接时确定并写入文件之中。
对于DLL来说,如果采用“完全重定位”,则可以在运行时任意拆分;如果采用“PIC”(位置无关代码),则同可执行文件。
完全重定位的条件是,在文件中保存了完整的重定位项表,符号表,符号名表,以及section header table。--当然,操作系统也要有相应的功能。
PIC的条件是,在编译时产生PLT和GOT表,通过这两个表实现代码的位置无关性。--绝大多数DLL采用这种方式。
------解决方案--------------------------------------------------------
此段非彼段
一个是CPU的段,一个是链接器的段
由于历史原因,用了同一个名字