2013-2-2 - simple-loader

来源:互联网 发布:整型变量的数据范围 编辑:程序博客网 时间:2024/04/30 18:18

目标:把主引导扇区改造成一个loader,从硬盘中将用户程序加载到内存中,之后将cpu处理权分配给用户程序。


1.NASM编译器使用汇编指令定义段:

SECTION 段名称

SEGMENT 段名称


2.intel 要求段在起始物理内存中的起始地址16字节对齐: align=16


3.db: 1个字节  dw: 2个字节 dw:4个字节


4.磁盘中的用户应用程序的格式:

 —程序总长度

      |

     入口点

      |

      段重定位表项数

      |

     段重定位表

--用户程序


5.loader的问题提出,为了实现loader的工作,需要解决如下三个问题:

1)如何找到磁盘中的用户程序位置?在哪里

2)找到磁盘中的具体位置后,加载到内存的什么位置?

3)具体如何加载?


6、通过编译器编译出来的执行文件中的汇编地址只是一个相对地址,只是段内的一个偏移地址。而程序中用户自定义的各个段地址也仅仅是段定义中下面那个代码的偏移地址。


具体工作流程(思路):

1)初始化:将引导扇区的段地址从偏移0x7c0开始。同时设定磁盘中的程序实际需要载入到的物理地址 。同时将该地址<<16,得到段地址,赋给ds,es

2)首次尝试通过给定的第一个扇区号去读取对应的磁盘程序(一个扇区 = 512bytes),因为根据用户程序的约定,第一个扇区中的程序必然包含了整个用户程序的描述信息(具体见上),通过读取第一个扇区,得到整个程序的长度。将磁盘上的数据加载到内存[DS:0x0000]处。

3)至于读取磁盘的扇区,具体的做法如下:

  3.1设置要读取的扇区数量,写入到0x1f2端口,设置al为要写入扇区的数量

  3.2设置起始LBA地址扇区号,由于28位扇区号太长放不下16位寄存器,所以分成4段,分别写入端口:0x1f3,0x1f4,0x1f5,0x1f6,注意0x1f6需要额外的设置其他标志位。

  3.3向端口0x1f7写入0x20的读取磁盘命令。

  3.4等待读写操作完成,0x1f7既是命令端口,也是状态端口。等待标志位被置位。

  3.5连续读取出磁盘中保存的数据,使用0x1f0端口,是一个16位端口。读取出的数据存放到DS制定的数据段,便宜地址由寄存器BX指定。

4)现在程序的前512字节已经读取了地址:[ds:0x0000]处,可以通过偏移读取到用户程序的长度,进而判断是否需要继续读取下面的扇区。如果占用多个扇区,那么走入一个循环,步长位512字节,重设ds段地址,调用读取磁盘接口,使所有的用户代码全部读取到制定内存上。

5)修改实际装载后的入口代码段基址,以及各个段的实际载入基址