《操作系统真相还原》二

文章详细介绍了MBR(主引导记录)的作用和功能,包括其在BIOS中的作用,实模式下的地址分配,以及如何通过BIOS中断显示字符。作者通过代码示例展示了如何清屏并在屏幕上显示1MBR,并解释了MBR如何通过读取硬盘数据加载loader到内存,从而进入更复杂的操作。loader的代码显示了LOADER字符串,表明成功过渡。
摘要由CSDN通过智能技术生成

前言

上次说到在屏幕上显示"1 MBR"。我们从BIOS进入MBR,在mbr里面调用BIOS中断,在屏幕上显示"1 MBR"。上次就到这里了。但是mbr的作用显然不止只要这些。接下来我们就是来完善MBR。

实模式地址分配

起始地址结束地址大小用途
FFFF0FFFFF16BBIOS入口地址
F0000FFFFF64KBBIOS代码,包括上面介绍的BIOS入口地址
C8000EFFFF160KB映射硬件适配器的ROM或者内存映射式I/O
C0000C7FFFF32KB显示适配器BIOS
B8000BFFFF32KB用于文本模式显示适配器
B0000B7FFF32KB用于黑白显示适配器
A0000AFFFF64KB用于彩色显示适配器
9FC009FFFF1KBEBDA(Extended BIOS Data Area)拓展BIOS数据区
07E009FBFF622080B可用区域
07C0007DFF512BMBR被BIOS加载到此处
0050007BFF30464B可用区域
00400004FF256BBIOS Data Area(BIOS数据区)
00000003FF1KBInterrupt Vector Table(中断向量表)

完善MBR

首先我们要知道MBR的作用是啥?MBR,又名Master Boot Record,即主引导记录,也被称为主引导扇区,主要记录着硬盘本身的相关信息以及硬盘各个分区的大小及位置信息。

书上个mbr介绍了很多,先调用BIOS的子功能显示字符。后面又从更底层,向显存写入数据,然后再屏幕显示字符。具体可以看开头的实模式地址分配。就是向地址B8000写入数据。从而让字符显示出来

;主引导程序 
;
;LOADER_BASE_ADDR equ 0xA000 
;LOADER_START_SECTOR equ 0x2
;------------------------------------------------------------
SECTION MBR vstart=0x7c00         
   mov ax,cs      
   mov ds,ax
   mov es,ax
   mov ss,ax
   mov fs,ax
   mov sp,0x7c00
   mov ax,0xb800
   mov gs,ax
​
; 清屏
;利用0x06号功能,上卷全部行,则可清屏。
; -----------------------------------------------------------
;INT 0x10   功能号:0x06       功能描述:上卷窗口
;------------------------------------------------------
;输入:
;AH 功能号= 0x06
;AL = 上卷的行数(如果为0,表示全部)
;BH = 上卷行属性
;(CL,CH) = 窗口左上角的(X,Y)位置
;(DL,DH) = 窗口右下角的(X,Y)位置
;无返回值:
   mov     ax, 0600h
   mov     bx, 0700h
   mov     cx, 0               ; 左上角: (0, 0)
   mov     dx, 184fh           ; 右下角: (80,25),
                   ; 因为VGA文本模式中,一行只能容纳80个字符,共25行。
                   ; 下标从0开始,所以0x18=24,0x4f=79
   int     10h                 ; int 10h
​
   ; 输出背景色绿色,前景色红色,并且跳动的字符串"1 MBR"
   mov byte [gs:0x00],'1'
   mov byte [gs:0x01],0xA4     ; A表示绿色背景闪烁,4表示前景色为红色
​
   mov byte [gs:0x02],' '
   mov byte [gs:0x03],0xA4
​
   mov byte [gs:0x04],'M'
   mov byte [gs:0x05],0xA4   
​
   mov byte [gs:0x06],'B'
   mov byte [gs:0x07],0xA4
​
   mov byte [gs:0x08],'R'
   mov byte [gs:0x09],0xA4
​
   jmp $               ; 通过死循环使程序悬停在此
​
   times 510-($-$$) db 0
   db 0x55,0xaa
​

代码先放到这里。

进入loader

到后面我们就进入loader了。进入loader需要mbr帮助,为啥要从mbr到loader呢?因为放到硬盘的0扇区,mbr只有512字节的空间,位置太小,啥事一个干不了。所以mbr需要从硬盘里面读取数据,加载到内存。然后mbr通过jmp指令跳转到刚刚加载的loader程序里面。先把代码贴上

;主引导程序 
;------------------------------------------------------------
%include "boot.inc"
SECTION MBR vstart=0x7c00         
   mov ax,cs      
   mov ds,ax
   mov es,ax
   mov ss,ax
   mov fs,ax
   mov sp,0x7c00
   mov ax,0xb800
   mov gs,ax
​
; 清屏
;利用0x06号功能,上卷全部行,则可清屏。
; -----------------------------------------------------------
;INT 0x10   功能号:0x06       功能描述:上卷窗口
;------------------------------------------------------
;输入:
;AH 功能号= 0x06
;AL = 上卷的行数(如果为0,表示全部)
;BH = 上卷行属性
;(CL,CH) = 窗口左上角的(X,Y)位置
;(DL,DH) = 窗口右下角的(X,Y)位置
;无返回值:
   mov     ax, 0600h
   mov     bx, 0700h
   mov     cx, 0                   ; 左上角: (0, 0)
   mov     dx, 184fh           ; 右下角: (80,25),
                   ; 因为VGA文本模式中,一行只能容纳80个字符,共25行。
                   ; 下标从0开始,所以0x18=24,0x4f=79
   int     10h                     ; int 10h
​
   ; 输出字符串:MBR
   mov byte [gs:0x00],'1'
   mov byte [gs:0x01],0xA4
​
   mov byte [gs:0x02],' '
   mov byte [gs:0x03],0xA4
​
   mov byte [gs:0x04],'M'
   mov byte [gs:0x05],0xA4     ;A表示绿色背景闪烁,4表示前景色为红色
​
   mov byte [gs:0x06],'B'
   mov byte [gs:0x07],0xA4
​
   mov byte [gs:0x08],'R'
   mov byte [gs:0x09],0xA4
     
   mov eax,LOADER_START_SECTOR   ; 起始扇区lba地址
   mov bx,LOADER_BASE_ADDR       ; 写入的地址
   mov cx,1          ; 待读入的扇区数
   call rd_disk_m_16         ; 以下读取程序的起始部分(一个扇区)
  
   jmp LOADER_BASE_ADDR
       
;-------------------------------------------------------------------------------
;功能:读取硬盘n个扇区
rd_disk_m_16:      
;-------------------------------------------------------------------------------
                       ; eax=LBA扇区号
                       ; ebx=将数据写入的内存地址
                       ; ecx=读入的扇区数
      mov esi,eax     ;备份eax
      mov di,cx       ;备份cx
;读写硬盘:
;第1步:设置要读取的扇区数
      mov dx,0x1f2
      mov al,cl
      out dx,al            ;读取的扇区数
​
      mov eax,esi      ;恢复ax
​
;第2步:将LBA地址存入0x1f3 ~ 0x1f6
​
      ;LBA地址7~0位写入端口0x1f3
      mov dx,0x1f3                       
      out dx,al                          
​
      ;LBA地址15~8位写入端口0x1f4
      mov cl,8
      shr eax,cl
      mov dx,0x1f4
      out dx,al
​
      ;LBA地址23~16位写入端口0x1f5
      shr eax,cl
      mov dx,0x1f5
      out dx,al
​
      shr eax,cl
      and al,0x0f      ;lba第24~27位
      or al,0xe0       ; 设置7~4位为1110,表示lba模式
      mov dx,0x1f6
      out dx,al
​
;第3步:向0x1f7端口写入读命令,0x20 
      mov dx,0x1f7
      mov al,0x20                        
      out dx,al
​
;第4步:检测硬盘状态
  .not_ready:
      ;同一端口,写时表示写入命令字,读时表示读入硬盘状态
      nop
      in al,dx
      and al,0x88      ;第4位为1表示硬盘控制器已准备好数据传输,第7位为1表示硬盘忙
      cmp al,0x08
      jnz .not_ready       ;若未准备好,继续等。
​
;第5步:从0x1f0端口读数据
      mov ax, di
      mov dx, 256
      mul dx
      mov cx, ax       ; di为要读取的扇区数,一个扇区有512字节,每次读入一个字,
               ; 共需di*512/2次,所以di*256
      mov dx, 0x1f0
  .go_on_read:
      in ax,dx
      mov [bx],ax
      add bx,2        
      loop .go_on_read
      ret
​
   times 510-($-$$) db 0
   db 0x55,0xaa
​

这里的写了rd_disk_m_16这个函数,里面接收三个参数,起始扇区lba地址,写入的地址,待读入的扇区数。就是从第二个扇区读取一个硬盘,也就是512个字节给放到LOADER_BASE_ADDR这个地址上去。LOADER_START_SECTOR和LOADER_BASE_ADDR都是boot.inc里面的。

代码如下

LOADER_BASE_ADDR equ 0x900 
LOADER_START_SECTOR equ 0x2

接下来就是从mbr进入loader了。进入loader就可以做很多事情了。

书上是先写了个显示字符的例子,看看是不是真的跳到loader里面去了。并且loader还正确运行了。

%include "boot.inc"
section loader vstart=LOADER_BASE_ADDR
​
; 输出背景色绿色,前景色红色,并且跳动的字符串"1 MBR"
mov byte [gs:0x00],'2'
mov byte [gs:0x01],0xA4     ; A表示绿色背景闪烁,4表示前景色为红色
​
mov byte [gs:0x02],' '
mov byte [gs:0x03],0xA4
​
mov byte [gs:0x04],'L'
mov byte [gs:0x05],0xA4   
​
mov byte [gs:0x06],'O'
mov byte [gs:0x07],0xA4
​
mov byte [gs:0x08],'A'
mov byte [gs:0x09],0xA4
​
mov byte [gs:0x0a],'D'
mov byte [gs:0x0b],0xA4
​
mov byte [gs:0x0c],'E'
mov byte [gs:0x0d],0xA4
​
mov byte [gs:0x0e],'R'
mov byte [gs:0x0f],0xA4
​
jmp $              ; 通过死循环使程序悬停在此

之后,我们再将loader.s和mbr.s写入img。运行看看效果。

dd if=mbr.bin of=hd60M.img bs=512 count=1 seek=2 conv=notrunc

写入完成后,启动虚拟机看看效果。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值