一、啟動區
ORG 0x7C00
JMP entry
DB 0x90
DB "HELLOIPL"
DW 512
DB 1
DW 1
DB 2
DW 224
DW 2880
DB 0xf0
DW 9
DW 18
DW 2
DD 0
DD 2880
DB 0,0,0x29
DD 0xffffffff
DB "HELLO-OS "
DB "FAT12 "
RESB 18
entry:
MOV AX, 0
MOV SS, AX
MOV SP, 0x7c00
MOV DS, AX
MOV AX, 0x0820
MOV ES, AX
MOV CH, 0 ;柱面0
MOV DH, 0 ;磁頭0
MOV CL, 2 ;扇區2
readloop:
MOV AL, 1 ;扇區數量
MOV BX, 0
MOV DL, 0 ;A驅動器
MOV AH, 0x02 ;讀扇區
INT 0x13
JNC next
error:
MOV AH, 0x0e
MOV AL, 'e'
INT 0x10
MOV AL, 'r'
INT 0x10
MOV AL, 'r'
INT 0x10
MOV AL, 'o'
INT 0x10
MOV AL, 'r'
INT 0x10
JMP fin
next:
MOV AX, ES
ADD AX, 0x20 ;下一扇區
MOV ES, AX
ADD CL, 1
CMP CL, 18
JBE readloop
MOV CL, 1
ADD DH, 1
CMP DH, 2
JB readloop ;讀反面的磁頭1
MOV DH, 0
ADD CH, 1
CMP CH, 10 ;讀10個柱面
JB readloop
JMP 0xc200
fin:
HLT
JMP fin
RESB 0x7dfe-$
DB 0x55, 0xaa
前面的一部分內容(entry之前)是img映象檔案的固定格式,後面是啟動區的正式內容
使用迴圈的方式讀磁碟,按扇區——磁頭——柱面的順序,一個磁頭18個扇區,一個柱面兩個磁頭。
程式的最後跳轉到0xc200,因為磁碟內容裝載在0x8000,檔案內容存在0x4200,所以kernal.com就在0x8000+0x4200=0xc200的位置
(二)作業系統本身
;kernal.nas
[BITS 16]
ORG 0xc200
MOV AH, 0x0e
MOV AL, 'A'
INT 0x10
fin:
HLT
JMP fin
輸出一個A字元。
使用nasm kernal.nas -o kernal.com
的方式編譯,裝載到img檔案中即可。程式的開始要指定ORG 0xc200, 這樣彙編器才能正確把標籤名對照到正確的地址。
(三)圖形模式切換
切換到圖形模式:
MOV AL, 0x13
MOV AH, 0x00
INT 0x10
解析度320*200的VGA圖形模式,VRAM的地址在0xa0000~0xaffff。
注意十六位下,用SI/DI定址只能定址到0x0000~0xffff的地址,所以要用暫存器定址。
描畫條紋圖案:
MOV AX,0xA000
MOV DS,AX
MOV AL, 0x13
MOV AH, 0x00
INT 0x10
MOV SI, 0x0000
L1:
MOV BX, SI
AND BL, 0x0f
MOV BYTE[DS:SI], BL
ADD SI, 1
CMP SI, 0xFFFF
JBE L1
fin:
HLT
JMP fin
參考書中第四天的內容寫的,不過暫時還未切換32位模式所以只能用匯編寫。用[DS:SI]的方式定址,16位下段號相當於[DS*16+SI],DS代入0xA000,SI代入0x0000,那麼[DS:SI]就是[0xA0000]。
上一節是在80*25的字元模式下描畫了一個文字A,這次我們嘗試著在圖形模式下描畫文字A,參考第五天中文字顯示的程式碼。
用匯編語言寫比較複雜的迴圈可能是比較麻煩...(
實現如下:
其實主體的結構不難,最難的其實是記憶體段的處理,訪問font_A的時候指定的是程式碼段暫存器CS,而訪問視訊記憶體需要指定資料段DS,還不能混用,如果給CS賦0xA0000就會出大問題。
[BITS 16]
ORG 0xc200
MOV AL, 0x13
MOV AH, 0x00
INT 0x10
;font_A
MOV CX, 0
MOV AX, 0xa000
MOV DS, AX
MOV SI, 0x0000
ADD SI, 8*320
ADD SI, 8
loop:
CMP CX, 16
JE fin
MOV BX, CX
MOV BH, BYTE[CS:font_A+BX]
AND BH, 0x80
CMP BH, 0
JE L1
MOV BYTE[DS:SI+0], 15
L1:
MOV BX, CX
MOV BH, BYTE[CS:font_A+BX]
AND BH, 0x40
CMP BH, 0
JE L2
MOV BYTE[DS:SI+1], 15
L2:
MOV BX, CX
MOV BH, BYTE[CS:font_A+BX]
AND BH, 0x20
CMP BH, 0
JE L3
MOV BYTE[DS:SI+2], 15
L3:
MOV BX, CX
MOV BH, BYTE[CS:font_A+BX]
AND BH, 0x10
CMP BH, 0
JE L4
MOV BYTE[DS:SI+3], 15
L4:
MOV BX, CX
MOV BH, BYTE[CS:font_A+BX]
AND BH, 0x08
CMP BH, 0
JE L5
MOV BYTE[DS:SI+4], 15
L5:
MOV BX, CX
MOV BH, BYTE[CS:font_A+BX]
AND BH, 0x04
CMP BH, 0
JE L6
MOV BYTE[DS:SI+5], 15
L6:
MOV BX, CX
MOV BH, BYTE[CS:font_A+BX]
AND BH, 0x02
CMP BH, 0
JE L7
MOV BYTE[DS:SI+6], 15
L7:
MOV BX, CX
MOV BH, BYTE[CS:font_A+BX]
AND BH, 0x01
CMP BH, 0
JE L8
MOV BYTE[DS:SI+7], 15
L8:
ADD CX, 1
ADD SI, 320
JMP loop
fin:
HLT
JMP fin
font_A:
DB 0x00,0x18,0x18,0x18,0x18,0x24,0x24,0x24
DB 0x24,0x7e,0x42,0x42,0x42,0xe7,0x00,0x00
話說在320*200的解析度下,8*16的字元看上去確實很大==