1、熟悉bochs中的调试方法
再修改MBR程序之前,也按书中要求熟悉一遍bochs中的各项调试命令,方便后续写操作系统时经常要查错纠错
2、完善我们的mbr
;主引导程序
;-------------------------------------------------------------
%include "boot.inc"
SECTION MBR vstart=0x7c00
mov ax,cs
mov ss,ax
mov es,ax
mov ss,ax
mov fs,ax
mov sp,0x7c00
mov ax,0xb800
mov gs,ax
;利用0x06号功能,上卷全部行,则可清屏
mov ax,0x0600
mov bx,0x0700 ;BH是设置缺省属性,属性是指背景色,前景色,是否闪烁等,例如07H表示黑底白字,70H表示灰底黑字等等。
mov cx,0x0000
mov dx,0x184f
int 0x10
;输出背景绿色,前景色红色,并且跳动的字符串"1 MBR"
mov byte [gs:0x00],'1'
mov byte [gs:0x01],0xA4 ;A表示绿色背景闪烁1010 0100b
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
mov eax,LOADER_START_SECTOR
mov bx,LOADER_BASE_ADDR
mov cx,1
call rd_disk_m_16
jmp LOADER_BASE_ADDR
;--------------------------------------------------
;功能为读取硬盘n个扇区
rd_disk_m_16:
;--------------------------------------------------
mov esi,eax
mov di,cx
;设置要读取的扇区数
mov dx,0x1f2
mov al,cl
out dx,al
mov eax,esi
;将LBA地址存入0x1f3-0x1f6
;LBA地址7-0位
mov dx,0x1f3
out dx,al
;LBA地址15-8位
mov cl,8
shr eax,cl
mov dx,0x1f4
out dx,al
;LBA地址23-16位
shr eax,cl
mov dx,0x1f5
out dx,al
;LBA地址24-27位
shr eax,cl
and al,0x0f
or al,0xe0 ;设置7-4位为1110,表示lba模式
mov dx,0x1f6
out dx,al
;向0x1f7端口写入读命令,0x20
mov dx,0x1f7
mov al,0x20
out dx,al
.not_ready:
nop
in al,dx
and al,0x88
cmp al,0x08
jnz .not_ready
;读数据
mov ax,di
mov dx,256
mul dx
mov cx,ax ;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
3、增加一简单的loader程序
因为完善后的mbr,要通过远跳转指令,转移到后续的loader执行,所以我也按照书中步骤增加了个简单的loader程序(后续再修改),目前为了演示mbr能成功跳转到loader
%include "boot.inc"
section loader vstart=LOADER_BASE_ADDR
mov byte [gs:0x00],'2'
mov byte [gs:0x01],0xA4
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 $ ;通过此死循环悬停在此
其中mbr和loader程序中都引用了boot.inc的头文件,我按照书中也建了个include文件夹,将需要用到的头文件放在include目录内,相当于我们的库文件目录,如下图所示
目前include目录下boot.inc文件内容如下图
;--------------------loader和kernel----------------------
LOADER_BASE_ADDR equ 0x900
LOADER_START_SECTOR equ 0x2
4、启动bochs,执行,验证程序运行的效果 (loader代码字符串最后一个字符应该是R,我写成了E,哈哈,不过不影响验证测试)