📄 boot.asm
字号:
org 0x7c00
jmp short LABEL_START
nop
%include "fat12hd.inc"
TopOfStack equ 07bffh ;栈顶
DisPosition db 0
%include "const.inc"
LABEL_START:
;清屏
mov ax, 0600h ; AH = 6, AL = 0h
mov bx, 0700h ; 黑底白字(BL = 07h)
mov cx, 0 ; 左上角: (0, 0)
mov dx, 0184fh ; 右下角: (80, 50)
int 10h ; int 10h
mov ax,cs
mov ds,ax
mov ss,ax
mov sp,TopOfStack
mov bp,sp
mov ax,BaseOfLoader
mov es,ax
mov bx,0
mov ax,BootMessage
mov dx,BootMessageLength
call DispStr
FIND_LOADER_IN_ROOTDIR:
cmp word [RootDirSecLeft],0
jz LOADER_NOT_FOUND
dec word [RootDirSecLeft]
mov ax,[SearchSec]
inc word [SearchSec]
mov cl,1 ;;7c84
call ReadSec
mov cx,16
FIND_LOADER_IN_SECTOR:
cmp cx,0
jz LOADER_NOT_FOUND_IN_SECTOR
dec cx
mov byte [DirNameLength],0bh
mov si,LoaderName
CMP_NAME_IN_ROOTENTRY:
cmp byte [DirNameLength],0
jz LOADER_FOUND
dec byte [DirNameLength]
lodsb
cmp al,byte [es:bx]
jz GO_ON_CMP
and bx,0ffe0h
add bx,20h
jmp FIND_LOADER_IN_SECTOR
GO_ON_CMP:
inc bx
jmp CMP_NAME_IN_ROOTENTRY
LOADER_FOUND:
mov ax,LoaderFoundMessage
mov dx,LoaderFoundLength
call DispStr
and bx,0ffe0h
add bx,1ah ;7cc6
mov ax,[es:bx]
mov bx,0
push ax
LOADING_LOADER:
add ax,AdjustParameter
mov cl,1 ;;7CD1
call ReadSec
pop ax
call GetFatNum
cmp ax,0fffh
jz LOADING_FINISHED
push ax
add bx,200h
jmp LOADING_LOADER
LOADING_FINISHED:
jmp BaseOfLoader:OffsetOfLoader
; jmp $
LOADER_NOT_FOUND_IN_SECTOR:
mov bx,0
jmp FIND_LOADER_IN_ROOTDIR
LOADER_NOT_FOUND:
mov ax,NoLoaderMessage
mov dx,NoLoaderMessageLength
call DispStr
jmp $
;函数功能及参数说明:
;功能:读入一个扇区进内存es:bx处
;参数:ax=扇区号,cl=要读入的扇区数
;影响寄存器:除参数外无
;bios功能int 13h的说明
;dh=磁头号,ch=柱面号,cl=起始扇区(注意:这里的起始扇区号为1~BPB_SecPerTrk)
;ah=2(功能号,2表示读),al=读几个扇区,dl=驱动器号
; -----------------------------------------------------------------------
; 怎样由扇区号求扇区在磁盘中的位置 (扇区号 -> 柱面号, 起始扇区, 磁头号)
; -----------------------------------------------------------------------
; 设扇区号为 x
; ┌ 柱面号 = y >> 1
; x ┌ 商 y ┤
; -------------- => ┤ └ 磁头号 = y & 1
; 每磁道扇区数 │
; └ 余 z => 起始扇区号 = z + 1
ReadSec:
push bp
mov bp,sp
push dx
mov dl,[BPB_SecPerTrk]
div dl
mov byte [bp-4],cl
inc ah
mov cl,ah ;得到起始扇区
mov byte [bp-5],al
shr al,1
mov ch,al ;得到柱面号
mov dh,[bp-5]
and dh,1 ;得到磁头号
mov dl, [BS_DrvNum] ;得到驱动器号
mov al,[bp-4] ;得到要读的扇区数
mov ah,2 ;读
int 13h
mov al,'.'
call DispChar
pop dx
mov sp,bp
pop bp
ret
;函数功能及参数说明:
;功能:得到fat簇号为ax的下一个簇号,返回值为ax
;参数:ax=fat簇号
;影响寄存器:除参数外无
GetFatNum:
push bp
mov bp,sp
push es
push bx
push dx
push cx
push ax
mov ax,0
mov es,ax
mov bx,01000h
pop ax
mov byte [IsOdd],0
mov dl,3
mul dl
mov dl,2
div dl
cmp ah,0
jz LABEL_GO_ON
mov byte [IsOdd],1
mov ah,0
LABEL_GO_ON:
xor dx,dx
mov cx,[BPB_BytsPerSec]
div cx ;商为fat号所在的扇区号,余数为在此扇区的第几个字节
add ax,1
mov cl,2
call ReadSec
cmp byte [IsOdd],0
jz NOT_ODD
jmp IS_ODD
IS_ODD:
add bx,dx
mov ax,[es:bx]
shr ax,4
jmp RETURN
NOT_ODD:
add bx,dx
mov ax,[es:bx]
and ax,0fffh
RETURN:
pop cx
pop dx
pop bx
pop es
mov sp,bp
pop bp
ret
;显示一字符串,ax=字符串地址,dx为字符串长度
;影响寄存器:除参数外无
DispStr:
push bp ;保存bp
push cx ;保存cx
push bx ;保存bx
push es ;保存es
mov bp, ax ; ?
mov ax, ds ; ? ES:BP = ???
mov es, ax ; ?
mov cx, dx ; CX = ???
mov ax, 01301h ; AH = 13, AL = 01h
mov bx, 0007h ; ???0(BH = 0) ????(BL = 07h)
mov dl, 0
mov dh,[DisPosition]
int 10h ; int 10h
inc byte [DisPosition]
pop ax
mov es,ax ;恢复es
pop bx ;恢复bx
pop cx ;恢复cx
pop bp ;恢复bp
ret
;在当前光标处显示一字符,al=要显示的字符
;影响寄存器:除参数外无
DispChar:
push bp
mov bp,sp
push ax
push bx
mov ah,0eh
mov bl,0fh
int 10h
pop bx
pop ax
mov sp,bp
pop bp
ret
LoaderName: db "LOADER BIN"
BootMessage: db "booting"
BootMessageLength equ 07h
NoLoaderMessage: db "no loader!"
NoLoaderMessageLength equ 0ah
LoaderFoundMessage: db "loader found!"
LoaderFoundLength equ 13
times 510-($-$$) db 0 ; 填充剩下的空间,使生成的二进制代码恰好为512字节
dw 0xaa55
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -