📄 learnosboot.asm
字号:
;∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑
;Boot.asm
;START:2006/4/11
;AUTHOR:Tresss
;SYSTEM:WinXP+nasm
;HomePage: http://www.writeos.com
;E-Mail:potianjing@gmail.com
;Character:BootLoader.
;Completed:2006.4.24
;nasm boot.asm
;
;∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑
[bits 16]
[org 0x7C00]
jmp short Main
NOP
;----------------Fat12分区数据区---------------------
OEM DB 'TresssOS'
ByteOfSec DW 0x200
SecOfClus DB 0x01
NumOfReci DW 0x0001
NumOfFats DB 0x02
NumOfDirs DW 0x00E0 ;十进制224
NumOfSec DW 0x0B40 ;2880
MediaBPB DB 0xF0
SecOfFats DW 0x0009
SecOfTrk DW 0x0012 ;18
NumOfHeader DW 0x0002
NumOfHide DD 0x00000000
TotalOfSec DD 0x00000000
NumOfDrv DB 0x00
Reserved DB 0x00
SigOfBoot DB 0x29
IDOfVol DD 0x00000000
LabOfVol DB 'Tresss 0.01'
TypeOfFile DB 'Fat12 '
;-------------------分区数据结束--------------------
Main:
Xor ax,ax
Mov ds,ax
mov ss,ax
mov es,ax
mov sp,0x7BF0
mov si,Msg
Call ShowMessage
xor ah,ah
;∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑
;准备读取根目录区数据
;内存的前500H被BIOS占用,所以此处加载到内存500H之后
;计算出线形扇区位置后
;调用ReadSectors来读取数据.
;磁头,磁道,扇区的换算过程由ReadSectors来解决
;∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑
mov al,[MemStart]
mov es,ax
mov al,[SecOfFats]
mov bl,[NumOfFats]
mul bl ;算出Fat区占用的扇区数
add al,[NumOfReci]
add al,[NumOfHide] ;AL为目录区起始扇区按现标准值,此时应该al=19
mov [FatFSec],al ;保存Fat之前的扇区总数
mov cx,ax ;将起始扇区记录到CL,供ReadSectors调用
mov al,[NumOfDirs]
mov bl,[SizeOfDir]
mul bl ;ax为目录区大小;
mov [SizeDRoot],ax ;记录目录区大小;
mov bx,[ByteOfSec]
div bx ;AL为目录区占用几个扇区;此时应为14
mov [RootDSec],al ;保存目录区占几个扇区到缓存区
xor si,si ;读取到0x50:00处
call ReadSectors
;------------------读取根目录完成--------------------
;∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑
;从500H处开始查找要加载的文件FileImport
;∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑
FindFile:
xor al,al
cmp [es:si],al ;0x50:00处,根目录数据的起始位置.
jz notok ;无效数据(0H)退出
mov cl,11
push si
mov di,FileImport
CmpLoop:
mov ah,[ds:di]
mov al,[es:si]
cmp ah,al
jnz CmpNext ;不相等则比较下一个文件名
inc si
inc di
loop CmpLoop ;比较下一个字符
pop si
jmp LoadFile ;找到文件,加载
CmpNext:
pop si
xor ah,ah
mov al,[SizeOfDir]
add si,ax ;指向下一个目录名.
mov ax,[SizeDRoot]
cmp si,ax ;比较是否已经查找到目录的最后
jb FindFile ;循环比较下一个文件名.
;----------------查找文件结束--------------------------
;∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑
;错误处理,此处应加入错误提示信息
;∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑
notok: ;错误处理,此处应显示一行信息.
xor ax,ax
mov es,ax
mov si,FileImport
Call ShowMessage
xor ax,ax
int 16h
;-------------------错误处理结束----------------------
;∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑
;加载Fat区数据至内存500H+SizeDRoot处
;SizeDRoot由上面加载目录区时算出并保存.
;es:si指向文件目录信息
;∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑
LoadFile:
;---------------先加载Fat区数据----------------------
push si
mov ax,[SizeDRoot] ;已加载目录区,此处跳过
mov si,ax
mov al,[SecOfFats] ;FAT占用扇区数,即读取的个数
mov cl,[NumOfReci] ;保留扇区数
add cl,[NumOfHide] ;确定起始位置
Call ReadSectors
pop si ;si为内核文件名在目录区的偏移
;----------------Fat加载完毕-------------------------
mov ax,Word [es:si+1ah]
push ax ;起始簇
xor ax,ax
mov si,ax ;内存起始位置
pop ax
push ax
;∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑
;加载内核文件
;加载到内存FileSeg:00处,此处FileSeg=9000h
;∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑
Loading:
push es ;保存原基地址
mov bx,FileSeg
mov es,bx
Call ReadCluster ;读取当前簇内容
pop es
xor ah,ah
mov al,[SecOfClus]
mov bl,[ByteOfSec]
mul bl ;ax为每一簇的大小
add si,ax ;内存缓存区后移一簇大小
pop ax ;取出簇号
push si ;保存缓存区位置
mov si,ax
shr si,01h ;取(簇号/2)因为链表信息位于(簇号/2+簇号)
pushf ;作用:保存cf状态
add si,ax ;si值为(簇号/2+簇号),即此簇在Fat区的相对偏移
mov ax,[SizeDRoot] ;目录区占用内存大小
add si,ax ;此时es:si为内存中当前簇信息
mov ax,[es:si]
popf ;取出cf判断.
jc GetHigh ;cf=1,即为奇数时取高十二位
and ax,0fffh ;否则取低十二位
jmp iseof
GetHigh:
mov cl,4
shr ax,cl
iseof:
cmp ax,0ff8h ;是否结束.
jae runknl ;链表结束后跳转到runknl
pop si
push ax
jmp Loading ;没有结束则跳转继续读取当前簇
runknl:
mov ax,FileSeg ;此处为显示读取的内容
mov ds,ax
xor ax,ax
mov si,ax
Call ShowMessage
; jmp dword FileSeg:00 ;若执行内核.则只需将此句代替上面五句
;∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑
;ReadCluster
;读取一个簇的数据到内存
;入口:al 要读取的扇区数,cl 起始扇区位置
;入口:es:si为要读取到的内存地址,函数自动转换为es:bx
;∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑
ReadCluster:
sub ax,2h
mov bl,[FatFSec]
add al,bl
mov bl,[RootDSec]
add al,bl
mov cl,al ;起始扇区
mov al,[SecOfClus] ;要读取的扇区数
;∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑
;ReadSectors
;读取硬盘扇区数据到内存
;入口:al 要读取的扇区数,cl 起始扇区位置
;入口:es:si为要读取到的内存地址,函数自动转换为es:bx
;∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑
ReadSectors:
pusha
push ax
mov ax,cx
mov bl,[SecOfTrk]
div bl ;al为线性磁道数;
inc ah
mov cl,ah ;Cl为实际要读取的扇区位置.
xor ah,ah
mov bl,[NumOfHeader]
div bl
mov ch,al ;要读取的磁道数
mov dh,ah ;余数为磁头号
xor dl,dl
pop ax ;要读取的扇区数
mov bx,si ;读取到es:bx
mov ah,02
int 13h
popa
ret
;∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑
;显示字符串
;参数 :DS:SI 为要显示的字符串.以00H结尾
;返回值 :无
;∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑
ShowMessage:
mov ah,0x0e
mov bh,0x00 ;页码
mov bl,0x0c ;前景色
.nextchar:
lodsb
or al,al ;显示的字符
jz .brs
int 0x10
jmp .nextchar
.brs
ret
Msg db "Welcome To www.writeos.com......"
Mturn db 13,10,2,3,">",0
MemStart db 0x50 ;最前的自由内存区500H
FileImport db "learnos txt",0
SizeOfDir db 32 ;目录区,一个目录信息占多大
FatFSec db 0 ;记录目录区之前有多少扇区
RootDSec db 0 ;记录目录区占多少扇区
SizeDRoot db 0 ;记录目录区占多当字节
FileSeg equ 0x800 ;加载文件偏移
times 510-($-$$) db 0
dw 0xaa55
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -