1.MBR 主引导记录
①当BIOS对基本的外设进行检查,建立好中断向量表等等以后,BIOS也就完成了他的任务了,下一棒就要交给MBR了
②MBR必须放在磁盘的0柱面0磁道的第一个扇区,并且扇区的最后两个字节必须是0x55,0xaa,用来标识他就是MBR。
③MBR必须被加载到0x7c00
2.注意点
①SECTION MBR vstart=0x7c00
这个参数让编译器将section中的数据的地址以vstart的值开始,不再从整个程序头开始。
并不代表写了这个参数 程序就自动加载到这个地址
加载到内存中的哪个位置 那是程序加载器的功能
编译器只负责编址,
②我们这里为什么要写vstart=0x7c00呢 , 以为BIOS会把MBR扇区加载到内存中0x7c00这个位置,我们的代码必须遵守这一规则
3.代码
我们写的MBR做了什么呢?
①清除屏幕
②在屏幕上显示HelloWorld
③从磁盘上在读四个扇区
(四个扇区里面就是Loader 也就是MBR要提交接力棒的那位)
④把扇区最后两个字节设置为0x55,0xaa
;MBR CODE
;COntrol Screen Memory
; B8000 - BFFFF
%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 fun ClearScreen
;INIT 0X10 ---->AH
MOV AX, 0x0600
MOV BX, 0x0700
MOV CX, 0
MOV DX, 0x184f
INT 0x10
; printf
MOV CX, 0x000B ;loop time
MOV BX, 0x0
MOV SI, 0x0
HelloWorld_start:
MOV AL, [Message+BX]
INC BX
MOV BYTE [GS:SI], AL
INC SI
MOV BYTE [GS:SI], 0xA4
INC SI
LOOP HelloWorld_start
Message db "Hello World"
MOV EAX, LOADER_START_SECTOR ; LBA addr 0x02
MOV BX, LOADER_BASE_ADDR; Memory Addr 0x900
MOV CX, 4; 4 sector
CALL ReadDisk16b ;16bit mode
JMP LOADER_BASE_ADDR+0x300
;****************************************
;*********read from disk****************
ReadDisk16b:
MOV ESI, EAX; copy eax
MOV DI, CX; copy cx
;set sector count 1 sector
MOV DX, 0x1f2
MOV AL, CL;
OUT DX, AL;
MOV EAX, ESI; recover eax
;0x1f3-0x1f6 set LBA addr
MOV DX, 0x1f3; 0-7-->
OUT DX, AL
MOV DX, 0x1f4; 8-15-->
MOV CL, 8
SHR EAX, CL; EAX>>8
OUT DX, AL
MOV DX, 0x1f5; 16-->23
SHR EAX, CL; EAX>>8
OUT DX, AL
MOV DX, 0x1f6; 24-->27
SHR EAX, CL; EAX>>8
AND AL, 0x0f
OR AL, 0xe0; 1110 MainSector LBA_Mode
OUT DX, AL
;send read command 0x20
MOV DX, 0x1f7
MOV AL, 0x20
OUT DX, AL
;check disk status same port 0x1f7
Disk_Not_Ready:
NOP
IN AL, DX
AND AL, 0x88; BSY DRQ
CMP AL, 0x08
JNZ Disk_Not_Ready
;read 0x1f0
MOV AX, DI; DI == 1
MOV DX, 256
MUL DX ; ax = dx*ax
MOV CX, AX ; count*512B/2 1WORD
MOV DX, 0x1f0
LoopRead:
IN AX, DX
MOV [BX], AX
ADD BX, 2
LOOP LoopRead
RET
TIMES 510-($-$$) db 0
db 0x55, 0xaa