30天自製作業系統 第3天 harib00b 注釋

2021-08-03 22:55:44 字數 3839 閱讀 7002

程式中的行55的執行的3種情況:

a是如果讀取磁碟順利,第一次就讀取成功,那麼就會進入fin語句塊,如果pc機有動作喚醒了cpu,那麼就繼續往下執行,由於error是跳轉語句塊,所以這裡不會執行error語句塊(如果沒有跳轉error的指令就不會執行error語句塊),所以此時si仍然等於0,那麼就進入putloop語句塊,由於si不等於msg,[si]的值應該是0,所以al等於0,那麼就會跳回到fin語句塊,也就不會在顯示屏上顯示內容(msg語句塊對應的內容),如果pc機有動作喚醒了cpu,那麼就繼續往下執行(語句84~86),結束啟動程式。

b是如果讀取磁碟出錯,但是在5次以內讀取磁碟成功,那麼si就等於(1~5)中的乙個值,然後就會進入fin語句塊,如果pc機有動作喚醒了cpu,那麼就繼續往下執行,由於error是跳轉語句塊,所以這裡不會執行error語句塊,所以此時si仍然等於(1~5)中的乙個值,那麼就進入putloop語句塊,由於si不等於msg,[si]的值應該是0,所以al等於0,那麼就會跳回到fin語句塊,也就不會在顯示屏上顯示內容(msg語句塊對應的內容),如果pc機有動作喚醒了cpu,那麼就繼續往下執行(語句84~86),結束啟動程式。

c是如果讀取磁碟5次後仍然出錯,那麼就會進入error語句塊,在error語句塊中把msg的值賦給si,由於只有jmp指令在執行跳轉語句塊之後還會回到原來的jmp指令的語句處繼續往下執行,現在的jae指令跳轉到error語句塊之後就不會再跳回jae指令的語句處,而是在error語句塊的下面繼續執行,那麼此時就會進入putloop語句塊,由於si等於msg,所以putloop語句塊就會經過多次迴圈在顯示屏上顯示內容(msg語句塊對應的內容),顯示完內容之後就會跳轉到fin語句塊,如果pc機有動作喚醒了cpu,那麼就繼續往下執行(語句84~86),結束啟動程式。

注意:跳轉指令中,只有jmp指令在執行完跳轉語句塊之後還會回到原來的jmp指令的語句處繼續往下執行,其它的跳轉指令(比如jnc指令、jae指令)跳轉到指定的語句塊之後就不會再跳回該跳轉指令的語句處,而是指定的語句塊的下面繼續執行。

下面是程式及其注釋:

; haribote-ipl

; tab=4

org 0x7c00 ; 指明程式的裝載位址

; 以下這段是標準fat12格式軟盤專用的**

jmp entry ; 啟動ipl

db 0x90 ; 啟動ipl之後,就可以設定下面的屬性

db "haribote" ; 啟動區的名稱可以是任意的字串(8字)

dw 512 ; 每個扇區(sector)的大小(必須為512位元組)

db 1 ; 簇(cluster)的大小(必須為1個扇區)

dw 1 ; fat的起始位置(一般從第乙個扇區開始)

db 2 ; fat的個數(必須為2)

dw 224 ; 根目錄的大小(一般設成224項)

dw 2880 ; 該磁碟的大小(必須是2880扇區)

db 0xf0 ; 磁碟的種類(必須是0xf0)

dw 9 ; fat的長度(必須是9扇區)

dw 18 ; 1個磁軌(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 ; 初始化暫存器; 讓累加暫存器ax的初始值為0

mov ss,ax ; 讓棧段暫存器ss的初始值為0

mov sp,0x7c00 ; 讓棧指標暫存器sp的初始值為0x7c00; 見上面的org,程式的起始位址就是0x7c00

mov ds,ax ; 讓資料段暫存器ds的初始值為0

; 閱讀磁碟

mov ax,0x0820 ; 讓累加暫存器ax的值為0x0820; 該語句的作用:軟盤資料載入到記憶體中的位置0x0820~0x83ff

mov es,ax ; 附加段暫存器es的值賦值為ax的值,即0x0820; 該語句的作用:指定記憶體位址,先用es指定大致的位址,下面再用bx指定其中的具體的位址,具體的記憶體位址是es*16+bx

mov ch,0 ; 柱面0; ch計數暫存器高位為0; 指定軟盤上資料載入的位置

mov dh,0 ; 磁頭0; dh資料暫存器高位為0

mov cl,2 ; 扇區2; cl計數暫存器低位為2

mov si,0 ; 記錄失敗次數的暫存器;si是源變址暫存器

retry:

mov ah,0x02 ; ah=0x02 ; ah累加暫存器高位的值為0x02; 該語句的作用:讀盤

mov al,1 ; 1個扇區; al累加暫存器低位的值為1

mov bx,0 ; bx基址暫存器的值為0; 指定記憶體位址,具體的位址,具體的記憶體位址是es*16+bx

mov dl,0x00 ; a驅動器; dl資料暫存器低位的值為0x00; 該語句的作用:dl用來指定驅動器號

int 0x13 ; 呼叫磁碟bios

jnc fin ; 沒出錯的話(進製標誌為0)跳轉到fin,出錯的話(進製標誌為1),繼續往下執行

add si,1 ; 往si加1

cmp si,5 ; 比較si與5

jae error ; 當si>=5時,跳轉到error

mov ah,0x00 ; 復位軟體狀態

mov dl,0x00 ; a驅動器

int 0x13 ; 呼叫磁碟bios

jmp retry ; 跳回retry重新執行

; 讓cpu睡眠,等待喚醒指令

fin:

hlt ; 讓cpu停止,等待指令喚醒

jmp fin ; 無限迴圈

error:

mov si,msg ; 此時msg的位址是0x7c74(根據對應的彙編指令確定的這個位址),這裡把這個值代入si暫存器中;si是源變址暫存器

putloop: ; 程式執行到(entry:)後,依次往下執行,執行到(jc error)處就跳到(error:)處執行,執行完(mov si,msg)後就繼續往下執行(putloop:)

mov al,[si] ; 把源變址暫存器si所儲存的內容放到累加暫存器低位al裡面去

add si,1 ; 給si加1

cmp al,0 ; 比較al是否等於0,如果al等於0,說明[si]儲存的內容(即msg儲存的內容,也就是位址0x7c74上儲存的內容)等於0,也就是內容為空

je fin ; 如果上面的條件成立就跳到fin中執行,如果不成立就繼續往下執行,下面開始顯示文字

mov ah,0x0e ; 顯示乙個文字

mov bx,15 ; 指定字元顏色

int 0x10 ; 呼叫顯示卡bios

jmp putloop ; 迴圈顯示文字

msg:

db 0x0a, 0x0a ; 2個換行

db "load error" ; 要顯示的文字

db 0x0a ; 換行

db 0

resb 0x7dfe-$ ; 填寫0x00,直到0x7dfe

db 0x55, 0xaa ; 表示這個扇區的開頭是啟動程式,並開始執行這個程式

30天自製作業系統 第3天

cf 進製標誌,1位暫存器 jc 若進製標誌是1,則跳轉 int 0x13 呼叫磁碟bios ah 0x00 系統復位 0x02 讀盤 0x03 寫盤 0x04 校驗 0x0c 尋道 al 處理物件的扇區數 ch 柱面號 0xff cl 扇區號 0 5位 柱面號 0x300 2 dh 磁頭號 dl ...

《30天自製作業系統》第4天

1.c語言與畫面顯示的練習 彙編與c 語言結合時能自由使用的寄存區只有 eax,ecx,edx3 個,其他寄存區用於記憶非常重要的值,只能讀不能寫。intel系列 cpu 8086 80186 286 386 486 pentium pentiumpro pentium2 pentium3 pent...

《30天自製作業系統》第6天

1.pic 可程式設計中斷控制器 pic 連線 8個中斷訊號,監視輸入管腳的 8個中斷訊號。主 pic irq0 irq7 irq2 連線到從 pic irq8 irq15 中斷發生後,cpu 命令pic傳送2 個位元組的資料,格式是 0xcd 0 cpu收到2 個位元組後把資料當做指令來執行。0x...