30天自制作業系統:第三天
對第二天程式碼進行了修改,只列印hello ,uos沒一點意思。
讀取磁碟上10個柱面的1-18個扇區,(目前ssd已經沒有柱面這個概念了)。讀出來的資料放入記憶體0x8200起始的地方。
啟動區放在0x8000記憶體扇區中。為什麼要放在0x8000以後的記憶體中的呢? 只是因為這塊記憶體沒有用而已。
為什麼要將啟動程式(img的0扇區)放在0x7c00處? 這是ibm規定的。
向一個空軟盤儲存檔案時:
1.檔名會寫在0x002600以後的地方。
2.檔案內容會寫在0x004200以後的地方。
所以若想啟動位於0x004200的程式,就得讓載入程式執行完成後跳轉到0x8000+0x4200=0xc200處。
作者這一塊寫的很混亂啊,我們們整理一下為啥是0xc200地址,看下圖:
bios會把磁碟0位置的內容拷貝到記憶體0x7c00這個位置然後跳過去執行,
也就是把A拷貝到了記憶體,然後執行A
A會把磁碟後面的內容從記憶體0x8200開始拷貝
這樣的話磁碟0x4200位置就會對應到記憶體0xC200
一個扇區512位元組,十六進位制表示就是0x200
程式的執行情況:
1.bios讀取磁碟0扇區到0x7c00處。
2.bios跳轉到0x7c00處開始執行,該處為ipl10.nas程式,該程式功能為載入磁碟[1-最後]扇區到記憶體的0x8200處。並跳轉到0xc200處執行。
3.0xc200處為asmhead.nas程式,該程式功能為,呼叫顯示卡bios,設定畫面模式,呼叫作業系統程式碼。
4.作業系統程式碼目前就一個功能就是讓cpu睡眠,開始進入c程式。
下面根據功能修改程式碼:
1.修改ipl.nas
ipl10.nas:
; haribote-ipl
; TAB=4
CYLS EQU 10 ; 宣告CYLS=10
ORG 0x7c00 ; 指明程式裝載地址
; 標準FAT12格式軟盤專用的程式碼 Stand FAT12 format floppy code
JMP entry
DB 0x90
DB "HARIBOTE" ; 啟動扇區名稱(8位元組)
DW 512 ; 每個扇區(sector)大小(必須512位元組)
DB 1 ; 簇(cluster)大小(必須為1個扇區)
DW 1 ; FAT起始位置(一般為第一個扇區)
DB 2 ; FAT個數(必須為2)
DW 224 ; 根目錄大小(一般為224項)
DW 2880 ; 該磁碟大小(必須為2880扇區1440*1024/512)
DB 0xf0 ; 磁碟型別(必須為0xf0)
DW 9 ; FAT的長度(必??9扇區)
DW 18 ; 一個磁軌(track)有幾個扇區(必須為18)
DW 2 ; 磁頭數(必??2)
DD 0 ; 不使用分割槽,必須是0
DD 2880 ; 重寫一次磁碟大小
DB 0,0,0x29 ; 意義不明(固定)
DD 0xffffffff ; (可能是)卷標號碼
DB "HARIBOTEOS " ; 磁碟的名稱(必須為11字?,不足填空格)
DB "FAT12 " ; 磁碟格式名稱(必??8字?,不足填空格)
RESB 18 ; 先空出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 SI,0 ; 記錄失敗次數暫存器
retry:
MOV AH,0x02 ; AH=0x02 : 讀入磁碟
MOV AL,1 ; 1個扇區
MOV BX,0
MOV DL,0x00 ; A驅動器
INT 0x13 ; 呼叫磁碟BIOS
JNC next ; 沒出錯則跳轉到next
ADD SI,1 ; 往SI加1
CMP SI,5 ; 比較SI與5
JAE error ; SI >= 5 跳轉到error
MOV AH,0x00
MOV DL,0x00 ; A驅動器
INT 0x13 ; 重置驅動器
JMP retry
next:
MOV AX,ES ; 把記憶體地址後移0x200(512/16十六進位制轉換)
ADD AX,0x0020
MOV ES,AX ; ADD ES,0x020因為沒有ADD ES,只能通過AX進行
ADD CL,1 ; 往CL裡面加1
CMP CL,18 ; 比較CL與18
JBE readloop ; CL <= 18 跳轉到readloop
MOV CL,1
ADD DH,1
CMP DH,2
JB readloop ; DH < 2 跳轉到readloop
MOV DH,0
ADD CH,1
CMP CH,CYLS
JB readloop ; CH < CYLS 跳轉到readloop
; 讀取完畢,跳轉到haribote.sys執行!
MOV [0x0ff0],CH ; 記下IPL讀到哪裡了
JMP 0xc200
error:
MOV SI,msg
putloop:
MOV AL,[SI]
ADD SI,1 ; 給SI加1
CMP AL,0
JE fin
MOV AH,0x0e ; 顯示一個文字
MOV BX,15 ; 指定字元顏色
INT 0x10 ; 呼叫顯示卡BIOS
JMP putloop
fin:
HLT ; 讓CPU停止,等待指令
JMP fin ; 無限迴圈
msg:
DB 0x0a, 0x0a ; 換行兩次
DB "load error"
DB 0x0a ; 換行
DB 0
RESB 0x7dfe-$ ; 填寫0x00直到0x001fe
DB 0x55, 0xaa
我們在使用段暫存器時,以ES:BX這種方式表示地址,寫成"MOV AL, [ES:BX]"她代表ES×16+BX記憶體地址。
2.修改asmhead.nas
; haribote-os boot asm
; TAB=4
;一些定義
BOTPAK EQU 0x00280000 ; bootpack�̃��[�h��
DSKCAC EQU 0x00100000 ; �f�B�X�N�L���b�V���̏ꏊ
DSKCAC0 EQU 0x00008000 ; �f�B�X�N�L���b�V���̏ꏊ�i���A�����[�h�j
; 有關BOOT_INFO
CYLS EQU 0x0ff0 ; 設定啟動區
LEDS EQU 0x0ff1
VMODE EQU 0x0ff2 ; 該位置儲存顏色數目的資訊,顏色的位數。
SCRNX EQU 0x0ff4 ; 該位置儲存 解析度的x
SCRNY EQU 0x0ff6 ; 該位置儲存 解析度的y
VRAM EQU 0x0ff8 ; 影像緩衝區的開始地址。
ORG 0xc200 ; 這個程式需要裝載到記憶體的什麼地方呢。
; 畫面設定
MOV AL,0x13 ; VGA顯示卡,320*320*8位彩色,調色盤模式。
MOV AH,0x00
INT 0x10 ;呼叫顯示卡bios的函式,切換顯示模式。
MOV BYTE [VMODE],8 ; 將畫面模式資訊儲存到這些記憶體地址中。
MOV WORD [SCRNX],320
MOV WORD [SCRNY],200
MOV DWORD [VRAM],0x000a0000
;VRAM指的時顯示卡記憶體,也就是用來顯示畫面的記憶體。這一塊記憶體地址都對應著畫面上的畫素。
;VRAM在0xa0000~0xaffff之間的64kb。 VRAM分佈在記憶體分佈圖中的好幾個不同的地方。
; 用bios取得鍵盤上各種led燈的狀態。
MOV AH,0x02
INT 0x16 ; keyboard BIOS
MOV [LEDS],AL
;=====================================後邊的留以後再看,這塊時呼叫bootpack.c程式的======================
; 防止PIC接受所有中斷
; AT相容機的規範、PIC初始化
; 然後之前在CLI不做任何事就掛起
; PIC在同意後初始化
MOV AL,0xff
OUT 0x21,AL
NOP ; ; 不斷執行OUT指令
OUT 0xa1,AL
CLI ;進一步中斷CPU
; ; 讓CPU支援1M以上記憶體、設定A20GATE
CALL waitkbdout
MOV AL,0xd1
OUT 0x64,AL
CALL waitkbdout
MOV AL,0xdf ; enable A20
OUT 0x60,AL
CALL waitkbdout
; 保護模式轉換
[INSTRSET "i486p"] ; 說明使用486指令
LGDT [GDTR0] ;設定臨時GDT
MOV EAX,CR0
AND EAX,0x7fffffff ; 使用bit31(禁用分頁)
OR EAX,0x00000001 ; bit0到1轉換(保護模式過渡)
MOV CR0,EAX
JMP pipelineflush
pipelineflush:
MOV AX,1*8 ; 寫32bit的段
MOV DS,AX
MOV ES,AX
MOV FS,AX
MOV GS,AX
MOV SS,AX
;bootpack傳遞
MOV ESI,bootpack ; 源
MOV EDI,BOTPAK ; 目標
MOV ECX,512*1024/4
CALL memcpy
; 傳輸磁碟資料
; 從引導區開始
MOV ESI,0x7c00 ; 源
MOV EDI,DSKCAC ; 目標
MOV ECX,512/4
CALL memcpy
; 剩餘的全部
MOV ESI,DSKCAC0+512 ; 源
MOV EDI,DSKCAC+512 ; 目標
MOV ECX,0
MOV CL,BYTE [CYLS]
IMUL ECX,512*18*2/4 ; 除以4得到位元組數
SUB ECX,512/4 ; IPL偏移量
CALL memcpy
; 由於還需要asmhead才能完成
; 完成其餘的bootpack任務
; bootpack啟動
MOV EBX,BOTPAK
MOV ECX,[EBX+16]
ADD ECX,3 ; ECX += 3;
SHR ECX,2 ; ECX /= 4;
JZ skip ; 傳輸完成
MOV ESI,[EBX+20] ; 源
ADD ESI,EBX
MOV EDI,[EBX+12] ; 目標
CALL memcpy
skip:
MOV ESP,[EBX+12] ; 堆疊的初始化
JMP DWORD 2*8:0x0000001b
waitkbdout:
IN AL,0x64
AND AL,0x02
JNZ waitkbdout ; AND結果不為0跳轉到waitkbdout
RET
memcpy:
MOV EAX,[ESI]
ADD ESI,4
MOV [EDI],EAX
ADD EDI,4
SUB ECX,1
JNZ memcpy ; 運算結果不為0跳轉到memcpy
RET
; memcpy地址字首大小
ALIGNB 16
GDT0:
RESB 8 ; 初始值
DW 0xffff,0x0000,0x9200,0x00cf ; 寫32bit位段暫存器
DW 0xffff,0x0000,0x9a28,0x0047 ; 可執行的檔案的32bit暫存器(bootpack用)
DW 0
GDTR0:
DW 8*3-1
DD GDT0
ALIGNB 16
bootpack:
3.加入bootpack.c作業系統程式碼
這個作業系統實現了一個最簡單的功能:讓cpu睡眠
void io_hlt(void);
void HariMain(void)
{
fin:
io_hlt(); /* 執行naskfunc.nas裡邊的_io_hlt()函式。 */
goto fin;
}
4.加入naskfunc.nas
加入這個檔案是因為c程式不能呼叫HLT指令,所以使用c程式呼叫匯程式設計序,在彙編程式中用HLT讓cpu睡眠。
; naskfunc
; TAB=4
[FORMAT "WCOFF"] ; 製作目標檔案的模式
[BITS 32] ; 製作32位模式用的機器語言
; 製作目標檔案的資訊。
[FILE "naskfunc.nas"] ; 原始檔名資訊
GLOBAL _io_hlt ; 程式中包含的函式名
;實際的函式
[SECTION .text] ;目標中間中寫了這些之後再寫程式
_io_hlt: ; void io_hlt(void); 這個函式只執行了一個HLT命令,讓cpu睡眠。
HLT
RET
5.執行結果
本文程式碼下載地址:https://download.csdn.net/download/u011164819/12981508
相關文章
- 30天自制作業系統-merk11的第三天作業系統
- 30天自制作業系統 For Linux作業系統Linux
- 《30天自制作業系統》譯者序(偽)作業系統
- 30天自制作業系統(一)啟動區作業系統
- 30天自制作業系統——第3天實驗總結作業系統
- 30天自制作業系統——第4天實驗總結作業系統
- 讀懂《30天自制作業系統》的捷徑作業系統
- 30天自制作業系統-merk11的第一天作業系統
- 由《30天自制作業系統》引發的漫畫創作作業系統
- 三十天自制作業系統(13)作業系統
- 釋出在《30天自制作業系統》之前的幫助閱讀貼作業系統
- 為什麼《30天自制作業系統》封面中的貓是兩隻尾巴作業系統
- 自制作業系統(一) 第一個作業系統作業系統
- 團隊作業sprint第三天
- 第三天
- 釘釘學習第三天作業
- 暑假第三天
- 10天衝刺第三天
- python第三天Python
- 第三天工作
- 日誌第三天
- 第三天隨筆
- 衝刺第三天
- 透過GRUB Multiboot2引導自制作業系統boot作業系統
- 團隊10天衝刺第三天
- 學習css第三天CSS
- golang學習第三天Golang
- 10衝刺第三天
- Scurm衝刺第三天
- 《作業系統30天》-合川秀實-學習日誌day11作業系統
- [TEAP早期試讀]《30天寫出你的作業系統》 - 挑戰多工作業系統
- Spring學習第三天Spring
- 團隊專案第三天
- 第六週第三天6.3
- 4.20第三天衝刺
- 第七週第三天7.3
- 第九周第三天9.3
- 七天用 Go 寫個 docker(第三天)GoDocker