加载程序(器)的工作流程

1.加载器

1.1加载器执行流程图

1.2加载器关键代码和函数

SECTION mbr align=16 vstart=0x7c00

align=16 :在汇编地址分配时地址是16的整数倍,即地址最低4位为0

vstart=0x7c00 :在进行编译时每条指令的汇编地址从0x7c00开始

calc_segment_base:                       ;计算16位段地址
                                         ;输入:DX:AX=32位物理地址
                                         ;返回:AX=16位段基地址 
         push dx                          
         
         add ax,[cs:phy_base]			 ;低16位偏移地址加上物理始址
         adc dx,[cs:phy_base+0x02]		 ;高16位偏移地址加上物理始址
         shr ax,4						 ;ax低4位肯定为0,可以舍去
         ror dx,4						 ;将dx的最低4位放到最高4位去
         and dx,0xf000					 ;将dx除最高4位清零
         or ax,dx						 ;将dx的最高4位保存到ax中,拼凑出20位的段地址
         
         pop dx
         
         ret

;-------------------------------------------------------------------------------
         phy_base dd 0x10000             ;用户程序被加载的物理起始地址
         
 times 510-($-$$) db 0					 ;$是当前汇编地址,$$是汇编始址,相减得程序的总长度
                  db 0x55,0xaa           ;合法的引导程序必须以 0x55 0xaa 结尾

引导程序开始于0x0000:0x7c00处,且汇编地址于物理地址一一对应。

即phy_base对应的地址值是相对于段首的距离+0x7c00

calc_segment_base进行32位的加法,并把加法结果保存在ax中

read_hard_disk_0:                        ;从硬盘读取一个逻辑扇区
                                         ;输入:DI:SI=起始逻辑扇区号
                                         ;      DS:BX=目标缓冲区地址
         push ax
         push bx
         push cx
         push dx
      
         mov dx,0x1f2
         mov al,1
         out dx,al                       ;读取的扇区数

         inc dx                          ;0x1f3
         mov ax,si
         out dx,al                       ;LBA地址7~0

         inc dx                          ;0x1f4
         mov al,ah
         out dx,al                       ;LBA地址15~8

         inc dx                          ;0x1f5
         mov ax,di
         out dx,al                       ;LBA地址23~16

         inc dx                          ;0x1f6
         mov al,0xe0                     ;LBA28模式,主盘
         or al,ah                        ;LBA地址27~24
         out dx,al

         inc dx                          ;0x1f7
         mov al,0x20                     ;读命令
         out dx,al

  .waits:
         in al,dx
         and al,0x88
         cmp al,0x08
         jnz .waits                      ;不忙,且硬盘已准备好数据传输 

         mov cx,256                      ;总共要读取的字数
         mov dx,0x1f0
  .readw:
         in ax,dx
         mov [bx],ax
         add bx,2
         loop .readw

         pop dx
         pop cx
         pop bx
         pop ax
      
         ret

告诉主硬盘的接口要读写的扇区数量、起始扇区号并等待硬盘准备好后就可以从16位端口读取数据

1.3磁盘访问指令

LBA号=C*磁头总数*每道扇区数+H*每道扇区数+(S-1)

主硬盘

主硬盘控制器端口共有8个,端口号分别为
0x1f0:16位端口,数据传输端口
0x1f1:错误类型返回
0x1f2:8位端口,设置读取的扇区数量
0x1f3:8位端口,扇区号低0~7位设置端口(LBA28模式)
0x1f4:8位端口,扇区号低8~15位设置端口(LBA28模式)
0x1f5:8位端口,扇区号低16~23位设置端口(LBA28模式)
0x1f6:8位端口,低四位设置扇区号低24~27位设置端口(LBA28模式)
0x1f6:高四位,第7、5位固定为1;第6位 置0表示CHS模式,置1表示LBA模式;第4位 置0表示主硬盘,置1表示从硬盘
0x1f7:8位端口,命令/状态端口;向这个端口传输0x20就表示 请求硬盘读,随后硬盘会每时每刻将它的状态信息传输到这个端口,一旦硬盘准备好了就可以开始传输数据;第7位 置0表示硬盘不忙,置1表示硬盘忙;第3位 置0表示未准备好与主机交换数据,置1 表示准备好与硬盘交换数据;第0位表示前一条命令执行错误,具体原因查看0x1f1端口
从硬盘

从硬盘控制器端口共有8个,端口号分别为0x170,0x171,0x172,0x173,0x174,0x175,0x176,0x177
————————————————
版权声明:本文为CSDN博主「柳家山头号矿工」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/dc12499574/article/details/124207945

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值