ASM:《X86汇编语言-从实模式到保护模式》第8章:实模式下硬盘的访问,程序重定位和加载

    第八章是一个非常重要的章节,讲述的是实模式下对硬件的访问(这一节主要讲的是硬盘),还有用户程序重定位的问题。现在整理出来刚好能和保护模式下的用户程序定位作一个对比。

★PART1:用户程序的重定位,硬盘的访问

1. 分段、段的汇编地址和段内汇编地址

       NASM编译器使用汇编指令“SECTION”或者“SEGMENT”来定义段。他的一般格式是SECTION 段名称或者SEGMENT段名称(段名称不能重复),另外NASM对段没有数量的限制,一个程序可以有很多的代码段和数据段。Intel处理器要求段在内存中的其是物理地址起码是16字节对齐的,而NASM提供了段的修饰符align,使每一个段可以16字节对齐或者32字节对齐,比如

        

ASM:《X86汇编语言-从实模式到保护模式》第8章:实模式下硬盘的访问,程序重定位和加载

       所谓段的汇编地址其实就是段内第一个元素(数据,指令)的汇编地址,16字节对齐的意思是所有段首的汇编地址都要可以被16整除,如果存在一个段要求16字节对齐,而这个段的前一个段长度不够使当前段不能16字节对齐,那么编译器会自动将前一个段补0来使这一个段满足16字节对齐。

       NASM编译器提供以下形式section.段名称.start来获得段的汇编地址,比如:

 

ASM:《X86汇编语言-从实模式到保护模式》第8章:实模式下硬盘的访问,程序重定位和加载

       另外段还可以加一个vsart修饰符,因为在NASM编译器中,即使你定义了一个段,段的汇编地址就是段内第一个元素的汇编地址,但是在引用某个标号的时候(包括section.段名称.start),这个标号的汇编地址还是从整个程序的开头开始计算的,而不是对段首的偏移。不过再加了vsart=0的时候,段内所有标号的地址都是相对于当前段首的偏移了(当然也可以设定为其他数值,标号的偏移值是在这个值的基础上加上与段首的偏移地址。)

2. 用户程序头部

       加载一个用户程序需要一个加载器(在实模式下),而加载器是不知道用户程序里面具体的结构和功能的,一个程序想要运行,那么这个程序就要满足运行环境的一些约定俗成的条件,也就是程序哪些部分要怎么写是固定的,现在我们在MBR加载一个程序也是一样的,只要用户程序在某些部分满足一些条件,我们的加载器就可以识别并加载它。

       一般来说,头部在源程序需要以一个段的形式存在,比如可以这样写:

     

ASM:《X86汇编语言-从实模式到保护模式》第8章:实模式下硬盘的访问,程序重定位和加载

       一般地,用户程序头部最起码要包含以下信息:

①:用户程序的尺寸,以字节位单位的大小。加载器将根据这个信息来决定读取多少个逻辑扇区(假如程序在磁盘上都是连续存放的)。

②:应用程序的入口点(Entry Point),包括段地址和偏移地址。用户程序需要给出自身第一条指令的位置,让加载器加载程序以后可以把控制权交给用户程序。

③:段的重定位表,用户程序可能不止一个段,而实际上每个用户程序编译后各个段的位置只是相对于程序的最开始的位置,加载器一定要根据程序加载的地方重新设定各个段的位置!段的数量要预先给定。在实模式下,段的 重定位就是重新设定每个段基地址(16位的),所以每个段都必须16字节对齐(因为可以加载在1MB内存的任何一个64KB的段,而我们无法用16字节表示1MB的位置,所以只能用双字来设定位置,最后要设定为16位的段地址),才能给出正确的段地址。

3. 外围设备和其接口

       在加载器根据跟定的用户程序在内存的位置给重新设定用户程序的入口点和给段重定位之前,需要把用户程序加载到相应内存位置,而用户程序一般是放在硬盘上的,所以加载器首先根据用户程序在硬盘上的逻辑扇区号来加载程序。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzyywz.html