3.6让MBR使用磁盘

简介: 3.6让MBR使用磁盘

3.6让MBR使用磁盘

这里通过讲解一个汇编程序讲解如何使用MBR去使用磁盘

改造MBR

boot.inc

;-------------   loader和kernel   ----------
LOADER_BASE_ADDR equ 0x900 ;表示loader加载的内存位置
LOADER_START_SECTOR equ 0x2;表示读取的磁盘数,用LBA方式描述的磁盘位置

boot.inc其实相当于一个配置文件,该文件目前定义了两个宏,LOADER_BASE_ADDR

LOADER_START_SECTOR

这两个宏。作用在程序里面已经表示出来了

mbr.S


;主引导程序 
;------------------------------------------------------------
%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;放在gs段寄存器中
; 清屏
;利用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地址0x2
   mov bx,LOADER_BASE_ADDR       ; 写入的地址0x9000
   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 ;为磁盘Primary通道设置Sector count
      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


%include "boot.inc"是让编译器nasm在编译之前把boot.inc包含进来,%include是nasm编译器中的预处理指令。

mov eax,LOADER_START_SECTOR ; 起始扇区lba地址0x2

mov bx,LOADER_BASE_ADDR ; 写入的地址0x9000

mov cx,1 ; 待读入的扇区数

这三行程序是在进入rd_disk_m_16程序之前传递的参数。

后面执行的是读取磁盘内容,并将磁盘内容写到规定的位置。

其中涉及的知识点比较多。

1.显示器文本显示模式的地址是0xb800

2.磁盘读写步骤

第一步:设置要读取的扇区数

第二步,将LBA地址存入0xlf3~0xlf6

第三步,向0xlf7端口写入读命令0x20

第四步,检测硬盘状态

第五步,从0x1f0端口读取数据

上面的数据是如何来的可以通过前面章节对硬盘的讲解。


实现内核加载器

%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 $          ; 通过死循环使程序悬停在此


目录
相关文章
|
7月前
|
IDE Linux 开发工具
磁盘
磁盘
141 0
|
2月前
|
存储 缓存 监控
磁盘I/O
【10月更文挑战第4天】磁盘I/O
55 2
|
3月前
用winhex查看mbr分区
用winhex查看mbr分区
|
7月前
|
存储 弹性计算 Shell
硬盘
【4月更文挑战第30天】
47 1
|
人工智能 缓存 运维
我,一块“烤熟”的硬盘
我,一块“烤熟”的硬盘
130 0
|
缓存 监控 算法
|
存储 小程序 虚拟化
|
存储 测试技术 数据中心
下一篇
DataWorks