计算机系统结构与操作系统实验三(2)-编写MBR主引导记录

📍前言

衔接上文《保姆级》一次成功安装bochs!!附带相应ubuntu版本和bochs版本

同时为了更好地方便之后代码的管理和书写,建议大家在ubuntu里安装vscode,同时配置shell命令和makefile文件,实现快速编译,还请利用几分钟时间配置一下《大大简化每次运行bochs的命令行》ubuntu里安装vscode + makefile文件基本编写 + shell命令,一次配置!终身受益!

📍实验准备

  1. 在vscode根目录文件夹PUBLIC下创建3-2文件夹,里面装这次实验的所有代码
    (可以看到,我的bochs也是安装在PUBLIC下的,所以跟3-2处同一目录,既方便管理也方便运行)
    在这里插入图片描述

  2. 创建makefile文件
    3-2文件夹里创建makefile文件,先不输入内容,待会再说
    在这里插入图片描述

  3. 创建run.sh文件
    PUBLIC文件夹里创建run.sh文件(与3-2文件夹同级!)
    在这里插入图片描述

总之,如下文件结构
在这里插入图片描述

📍实验要求

  1. 编写mbr.S文件
    编写MBR主引导程序代码mbr.S,程序中用中断方式显示“mbr+自己的姓名”,如“mbr-zhangsan”。使用自己的配色

  2. 验证mbr.S对loader.S的初步加载
    loader.S是内核加载器,但在本次3-2实验中,暂不实现内核加载功能,而是简单地实现用显存方式打印字符功能,用于验证mbr对它所在的硬盘块的加载。
    字符显示“loader+自己的姓名”,如“loader-zhangsan”。使用自己的配色。
    将loader.S编译并将loader.bin写入硬盘

📍实验过程

📍📍运行mbr.S文件

在3-2文件夹内创建boot文件夹,再在boot文件夹内创建mbr.S文件
在这里插入图片描述
mbr.S内容如下👇

;主引导程序 
;------------------------------------------------------------
SECTION MBR vstart=0x7c00         
   mov ax,cs      
   mov ds,ax
   mov es,ax
   mov ss,ax
   mov fs,ax
   mov sp,0x7c00

; 清屏 利用0x06号功能,上卷全部行,则可清屏。
; -----------------------------------------------------------
;INT 0x10   功能号:0x06	   功能描述:上卷窗口
;------------------------------------------------------
;输入:
;AH 功能号= 0x06
;AL = 上卷的行数(如果为0,表示全部)
;BH = 上卷行属性
;(CL,CH) = 窗口左上角的(X,Y)位置
;(DL,DH) = 窗口右下角的(X,Y)位置
;无返回值:
   mov     ax, 0x600
   mov     bx, 0x700
   mov     cx, 0           ; 左上角: (0, 0)
   mov     dx, 0x184f	   ; 右下角: (80,25),
			   ; VGA文本模式中,一行只能容纳80个字符,25行。
			   ; 下标从0开始,所以0x18=24,0x4f=79
   int     0x10            ; int 0x10

;;;;;;;;;    下面这三行代码是获取光标位置    ;;;;;;;;;
;.get_cursor获取当前光标位置,在光标位置处打印字符.
   mov ah, 3		; 输入: 3号子功能是获取光标位置,需要存入ah寄存器
   mov bh, 0		; bh寄存器存储的是待获取光标的页号

   int 0x10		; 输出: ch=光标开始行,cl=光标结束行
			; dh=光标所在行号,dl=光标所在列号

;;;;;;;;;    获取光标位置结束    ;;;;;;;;;;;;;;;;

;;;;;;;;;     打印字符串    ;;;;;;;;;;;
   ;还是用10h中断,不过这次是调用13号子功能打印字符串
   mov ax, message 
   mov bp, ax		; es:bp 为串首地址, es此时同cs一致,
			; 开头时已经为sreg初始化

   ; 光标位置要用到dx寄存器中内容,cx中的光标位置可忽略
   mov cx, 15		; cx 为串长度,不包括结束符0的字符个数
   mov ax, 0x1301	; 子功能号13是显示字符及属性,要存入ah寄存器,
			; al设置写字符方式 ah=01: 显示字符串,光标跟随移动
   mov bx, 0x2		; bh存储要显示的页号,此处是第0,
			; bl中是字符属性, 属性黑底绿字(bl = 02h)
   int 0x10		; 执行BIOS 0x10 号中断
;;;;;;;;;      打字字符串结束	 ;;;;;;;;;;;;;;;

   jmp $		; 使程序悬停在此

   message db "mbr - luohaojia"
   times 510-($-$$) db 0
   db 0x55,0xaa

makefile内容👇

.PHONY:build burn clean

mbr_source=boot/mbr.S
mbr_target=boot/mbr.bin

hard_disk=/home/lhj/Public/bochs/bin/hd60M.img

build:
		nasm -o $(mbr_target) $(mbr_source)
burn:
		dd if=$(mbr_target) of=$(hard_disk) bs=512 count=1 conv=notrunc

run.sh内容👇

cd 3-2
make build
make burn

cd /home/lhj/Public/bochs/bin
./bochs -f lhjbochsrc.disk

打开vscode内置的终端(快捷键:ctrl + ~),输入:./run.sh
在这里插入图片描述
ok,按一个回车(默认选择为6),再按一个c(表示continue)
在这里插入图片描述

📍📍验证mbr.S对loader.S的初步加载

在boot文件夹里创建loader.S文件
在这里插入图片描述
loader.S内容👇

%include "boot.inc"
section loader vstart=LOADER_BASE_ADDR

; 输出背景色绿色,前景色红色,并且跳动的字符串"1 MBR"
mov byte [gs:0x00],'l'
mov byte [gs:0x01],0xA4     ; A表示绿色背景闪烁,4表示前景色为红色

mov byte [gs:0x02],'o'
mov byte [gs:0x03],0xA4

mov byte [gs:0x04],'a'
mov byte [gs:0x05],0xA4   

mov byte [gs:0x06],'d'
mov byte [gs:0x07],0xA4

mov byte [gs:0x08],'e'
mov byte [gs:0x09],0xA4

mov byte [gs:0x0a],'r'
mov byte [gs:0x0b],0xA4

mov byte [gs:0x0c],'-'
mov byte [gs:0x0d],0xA4

mov byte [gs:0x0e],'l'
mov byte [gs:0x0f],0xA4

mov byte [gs:0x10],'u'
mov byte [gs:0x11],0xA4

mov byte [gs:0x12],'o'
mov byte [gs:0x13],0xA4

mov byte [gs:0x14],'h'
mov byte [gs:0x15],0xA4

mov byte [gs:0x16],'a'
mov byte [gs:0x17],0xA4

mov byte [gs:0x18],'o'
mov byte [gs:0x19],0xA4

mov byte [gs:0x1a],'j'
mov byte [gs:0x1b],0xA4

mov byte [gs:0x1c],'i'
mov byte [gs:0x1d],0xA4

mov byte [gs:0x1e],'a'
mov byte [gs:0x1f],0xA4

jmp $		       ; 通过死循环使程序悬停在此

在boot文件夹里创建include文件夹,include文件夹里再创建boot.inc文件
在这里插入图片描述
boot.inc内容👇

;-------------	 loader和kernel   ----------
LOADER_BASE_ADDR equ 0x900 
LOADER_START_SECTOR equ 0x2

修改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

; 清屏
;利用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

	 
   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~27or al,0xe0	   ; 设置74位为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

修改makefile文件内容👇

.PHONY:build burn

mbr_source=boot/mbr.S
mbr_target=boot/mbr.bin
loader_source=boot/loader.S
loader_target=boot/loader.bin
hard_disk=/home/lhj/Public/bochs/bin/hd60M.img

build:
		nasm -I boot/include/ -o $(mbr_target) $(mbr_source)
		nasm -I boot/include/ -o $(loader_target) $(loader_source)
burn:
		dd if=$(mbr_target) of=$(hard_disk) bs=512 count=1 conv=notrunc
		dd if=$(loader_target) of=$(hard_disk) bs=512 count=1 seek=2 conv=notrunc

ok,打开终端,启动bochs吧!(图中红框为编译命令,红框下为bochs启动界面,是不是很方便?!)
在这里插入图片描述

老规矩,按个回车,按个c
在这里插入图片描述

本实验所有源码👉👉👉计算机系统结构与操作系统实验三bochs源代码

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值