今天的程序編寫倒不是很長時間,但是DEBUG花了我好長時間,具體前幾次崩潰的原因沒有找出來,但是最終可以運行了。
截個圖片,然后是匯編程序。
org 0x100
[bits 16]
jmp loaderStart
_GRAPH_SEG_OFFSET_ equ 0xb800
_RootEntCnt_ equ 0xe0
BS_OEMName db 'XXXXXXXX'
BPB_BytsPerSec dw 0x200
BPB_SecPerClus db 1
BPB_RsvdSecCnt dw 1
BPB_NumFATs db 2
BPB_RootEntCnt dw _RootEntCnt_
BPB_totSec16 dw 0xb40
BPB_Media db 0xf0
BPB_FATSz16 dw 9
BPB_SecPerTrk dw 0x12
BPB_NumHeads dw 2
BPB_HiddSec dd 0
BPB_totSec32 dd 0
BS_DrvNum db 0
BS_Reserved1 db 0
BS_BootSig db 0x29
BS_VolID dd 0
BS_VolLab db '11111111111'
BS_FileSysType db 'FAT12?? '
parameters:
?screenPo dd 0
?STR_LEN equ 12
?bootStr db 'Loading...? '
?noLoaderStr db 'No Kernel...'
?ready db 'Ready?????? '
?KernelBase equ 0x8000
?KernelOffset equ 0x0
?rootEntryNum db _RootEntCnt_
?loaderName db 'KERNEL? BIN'
loaderStart:
?mov ax,cs
?mov ds,ax
?mov es,ax
?mov ss,ax
?mov sp,0100
?mov ax,_GRAPH_SEG_OFFSET_
?mov gs,ax
?
?mov dh,0
?call displayStr
?
?xor ah,ah
?mov dl,[BS_DrvNum]
?int 0x13
?
?mov ax,KernelBase
?mov es,ax
?mov bx,0
?mov ax,19
?mov cl,14
?call readSector
?
?
?xor edi,edi
?
anotherFile:
?xor esi,esi
?cmp byte [rootEntryNum],0
?je noLoader
?
nextChar:
?mov al,byte [es:edi]
?cmp byte [ds:loaderName+si],al
?jne notThisFile
?cmp si,10
?je found
?inc esi
?inc edi
?jmp nextChar
?
?notThisFile:
?shr edi,5
?inc edi
?shl edi,5
?dec byte [rootEntryNum]
?jmp anotherFile
?
noLoader:
?mov dh,1
?call displayStr
?jmp $
?
found:
?mov dh,2
?call displayStr
?
?mov ax,word [es:edi+(0x10)]
?mov cl,1
?
?push ax
?mov ax,KernelBase
?mov es,ax
?mov ebx,KernelOffset
?pop ax
?
?readEntry:
?
?cmp ax,0xfff
?je readEnd
?push ax
?add ax,19+14-2
?call readSector
?pop ax
?
?add ebx,512
?call getFATEntry
?
?jmp readEntry
?readEnd:
?
?jmp toProtectMode
displayStr:
?; dh: String index
?push cx
?push ax
?push bx
?push esi
?push edi
?mov cx,STR_LEN
?mov edi,dword [screenPo]
?mov esi,bootStr
?xor eax,eax
?mov al,dh
?mov bl,STR_LEN
?mul bl
?add esi,eax
?.1:
?lodsb
?mov [gs:edi],al
?inc edi
?inc edi
?loop .1
?
?mov dword [screenPo],edi
?pop edi
?pop esi
?pop bx
?pop ax
?pop cx
?ret
readSector: ;ax: starting sector cl:number of sectors
?; ah 0x2????????? al:number of sector to read
?; ?????bx: es:bx
?; ch:cylinder???cl:start sector
?; dh:head?num???dl:Drive
?push bp
?mov bp,sp
?push cx
?push dx
?push ax
?
?mov dl,[BPB_SecPerTrk]
?div dl
?mov cl,ah
?inc cl
?
?mov ch,al
?shr ch,1
?
?mov dh,al
?and dh,1
?
?mov dl,byte [BS_DrvNum]
?
?.1:
?mov ah,2
?mov al,byte [bp-2]
?int 0x13
?jc .1
??
?pop ax
?pop dx
?pop cx
?pop bp
?ret
?
getFATEntry:
?FATBaseInMem equ 0x7000
?;ax is the entry number
?;return ax is the next entry
?
?push es
?push bx
?push dx
?push cx
?
?mov bx,FATBaseInMem
?mov es,bx
?
?mov bx,3
?mul bx ;dx:ax
?mov bx,2
?div bx ;dx is the rest
?push dx
?
?xor dx,dx
?mov bx,[BPB_BytsPerSec]
?div bx
?mov cl,2
?xor bx,bx
?add ax,1
?call readSector
?mov bx,dx; mov byte index
?
?pop dx
?xor ax,ax
?cmp dx,0
?jne oddPart
?
?mov ax,word [es:bx]
?and ax,0x0fff
?
?jmp after
?oddPart:
?
?mov ax,word [es:bx]
?shr ax,4
?after:
?pop cx
?pop dx
?pop bx
?pop es
?
?ret
?
?
toProtectMode:
?jmp start
?
%macro Descriptor 3
?dw %2 & 0xffff
?dw %1 & 0xffff
?db (%1 >> 16) & 0xff
?dw ((%2 & 0x0f0000) >> 8) | (%3 & 0xf0ff)
?db (%1 >> 24) & 0xff
%endmacro
DummyGDT: Descriptor 0,0,0
CodeGDT: Descriptor 0,0xfffff,1100000010011010b
DataGDT: Descriptor 0,0xfffff,1000000010010010b
ScreenGDT: Descriptor 0xb8000,0xffff,0000000010010010b
GDTPtr dw $-DummyGDT-1
?dd 0x9000*0x10+DummyGDT
CodeSelector equ CodeGDT-DummyGDT
DataSelector equ DataGDT-DummyGDT
ScreenSelector equ ScreenGDT-DummyGDT
start:
?call killMotor
?cli
?mov dh,2
?call displayStr
?
?lgdt [GDTPtr]
?
?in al,0x92
?or al,10b
?out 0x92,al
?
?mov eax,cr0
?or eax,1
?mov cr0,eax
?
?jmp dword CodeSelector:(0x9000*0x10+ProtectMode)
killMotor:
?push dx
?mov dx,0x3f2
?mov al,0
?
?out dx,al
?pop dx
?ret
[bits 32]
ProtectMode:
?mov ax,ScreenSelector
?mov gs,ax
?xor edi,edi
?.again:
?inc byte [gs:edi]
?jmp .again