操作系統實驗七:保護模式之中斷測試實驗

我對中斷的理解:

    中斷,顧名思義,就是在遇到特殊的情況時,停下當前正在做的事情,轉去幹其他(根據特殊情況預先設計好的)事情,完成後(並不一定非要)再繼續之前做的事情。

   首先說說“去幹其他(根據特殊情況預先設計好的)事情”。

   我們可以預先設計好256件事情(處理函數),然後使用0~255這256個編號(中斷向量號)表示代指。“事情”根據是否可以再次打斷(中斷),分爲中斷門(不可以被打斷)和陷阱門(可以再次被打斷)。

   下面解釋一下所謂的“遇到特殊的情況”,這個特殊的情況按照觸發類型可以分爲兩類:

   自動產生:自動產生的意思就是程序自己根據需要自己主動觸發的中斷,也就是使用int指令+中斷號觸發的。對於所有的256箇中斷,都可以使用int指令觸發。   

   被動產生:被動產生,就是系統硬性規定的,在遇到某種指定的情況,就觸發對應中斷向量號的中斷。
具體而言如下表:(摘自《自己動手寫內核系列_skelix》天衣有縫,有稍微修改)

中斷向量號   觸發原因
0x00           除零錯
0x01           調試異常
0x02           非可屏蔽中斷 (NMI)
0x03           斷點 (INT 3 指令)
0x04           溢出 (INTO 指令)
0x05           越界 (BOUND 指令)
0x06           無效的指令
0x07           無協處理器
0x08           雙重錯誤
0x09           協處理器越界
0x0A           無效的 TSS
0x0B           段不存在
0x0C           棧溢出
0x0D           通用保護異常(內存引用或其他檢查保護),Windows 9x 藍屏就是它的傑作
0x0E           頁錯誤
0x0F           Intel 保留
0x10           協處理器錯誤
0x11-0x19      Intel 保留

需要說明的有兩點:
    一.0x11~0x19這12箇中斷向量號, Intel預定了,但是並沒有實際使用上,但將來可能會用到。因此我們可以在編寫操作系統的使用直接拿來用,但是這樣會有一定風險,要是Intel的下一代產品裏使用了這些中斷向量號,我們想要兼容它,就不得不修改代碼將這幾個中斷向量號讓出來。
    二.上表中觸發的原因,基本都是程序運行時發生錯誤產生的(0x02號中斷除外),可以稱之爲內部中斷。與之相對應的稱作外部中斷的東西,就是由於計算機硬件(鍵盤,鼠標等)觸發的。這些中斷是可以屏蔽掉(忽略掉)的。想要響應這些中斷,也需要分配相應的中斷向量號才行。具體的內容就是下面要講到的可編程中斷控制器8259A。


可編程中斷控制器8259A:

8259A分自從兩塊,每一塊都可以接收8個不同觸發事件的信號,具體如下:(摘自《自己動手寫操作系統》於源)

主 8259A
序號        觸發源頭
IRQ0        時鐘
IRQ1        鍵盤
IRQ2        來自 從 8259A
IRQ3        串口2
IRQ4        串口1
IRQ5        LPT2
IRQ6        軟盤
IRQ7        LPT1

從 8259A
IRQ8        實時時鐘
IRQ9        重定向IRQ2
IRQ10       保留
IRQ11       保留
IRQ12       PS/2 鼠標
IRQ13       FPU 異常
IRQ14       AT 溫盤
IRQ15       保留

    通過編程,可以指定這些中斷事件對應哪些中斷向量號、是否使用 從 8259A ,以及屏蔽哪些中斷信號。具體的方法請參考pm32.c中的Init8259A()函數。

    瞭解了中斷源(觸發源),以及中斷源需要的一一對應關係的中斷向量號,最後就是對各個中斷向量號指定處理的動作(處理函數)了。這個我們在實驗任務門的使用已經很熟悉了,就是要創建一個IDT(中斷描述符表),這個IDT數組的序號就對應着中斷向量號。通過宏Gate中的選擇子和偏移量來指定處理的動作(處理函數)。使用lidt系統指令來加載這個IDT。
    需要特別說明的是,IDT這個數組中,每一個元素(中斷)佔8字節,若定義256箇中斷的話,需要2048字節的空間,這遠遠超出了引導扇區512字節的限制,因此與對付上一次實驗中的TSS類似,直接使用內存中不會用到的空間。先是定義一個只有一個元素的IDT,然後通過彙編指令重複複製到預先決定好的內存地址,然後再初始化具體的內容(對特定的中斷向量指定特定的處理函數)。


此次實驗的流程:
    1.跳轉到保護模式
    (pm32.c中main函數)
    2.重新加載新的GDT
    3.顯示字符串:This is Protect model.
    4.爲IDT模板設置一個默認函數
    5.將IDT模板重複複製到指定的內存地址
    6.爲IDT 0x20中斷(定時器中斷)設置一個處理函數,不斷循環加一修改顯示的字符
    7.爲IDT 0x80中斷設置一個處理函數:顯示字符“I”
    8.加載中斷描述符IDT
    9.進行中斷測試(使用int指令調用任意的中斷,使用sti指令啓用外部中斷使得定時器中斷產生效果等)

以下爲此次實驗代碼:
code:run.c

 

code:pm.h

 

code:pm16.c

 

code:pm32.c

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章