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


目录
相关文章
|
SQL 关系型数据库 MySQL
实时计算 Flink版操作报错合集之报错:org.apache.flink.table.api.validationexception如何解决
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
1134 1
|
人工智能 数据可视化 API
Dify-生成式 AI 应用创新引擎,本地搭建以及使用
Dify-生成式 AI 应用创新引擎,本地搭建以及使用
4724 1
|
存储 Linux 网络安全
在 Linux 中通过 SSH 执行远程命令时,无法自动加载环境变量(已解决)
SSH远程执行命令时遇到“命令未找到”问题,原因是Linux登录方式不同导致环境变量加载差异。解决方案:将环境变量写入`/etc/profile.d/`下的文件,或手动在命令前加载环境变量,如`source /etc/profile`。
1160 0
|
资源调度 安全 Ubuntu
CVE-2021-3560漏洞复现及原理分析
CVE-2021-3560漏洞复现及原理分析
396 0
成功解决 cl: 命令行 error D8021 :无效的数值参数“/Wno-cpp” 和 cl: 命令行 error D8021 :无效的数值参数“/Wno-unused-function”
成功解决 cl: 命令行 error D8021 :无效的数值参数“/Wno-cpp” 和 cl: 命令行 error D8021 :无效的数值参数“/Wno-unused-function”
成功解决 cl: 命令行 error D8021 :无效的数值参数“/Wno-cpp” 和 cl: 命令行 error D8021 :无效的数值参数“/Wno-unused-function”
|
Linux
nasm简单用法和dd指令解析
nasm简单用法和dd指令解析
404 0
3.4bochs的调试方法
3.4bochs的调试方法
393 0
|
编译器 程序员 索引
3.2.CPU中的实模式
3.2.CPU中的实模式
257 0
|
数据格式
3.3让我们直接对显示器说点什么吧
3.3让我们直接对显示器说点什么吧
191 0
|
Windows
实验二用机器指令和汇编指令编程
实验二用机器指令和汇编指令编程
216 0