跳轉至內容

x86 彙編/可程式設計中斷控制器

來自華夏公益教科書,開放的書籍,開放的世界

最初的 IBM PC 包含一個名為 **可程式設計中斷控制器** 的晶片,用於處理來自系統的傳入中斷請求,並以有序的方式將它們傳送到 MPU 進行處理。最初的中斷控制器是 8259A 晶片,雖然現代計算機將使用更新的變體。最常見的替代品是 APIC (高階可程式設計中斷控制器),它本質上是舊 PIC 晶片的擴充套件版本,以保持向後相容性。本頁將介紹 8259A。

中斷路徑,從硬體到 CPU

8259A 的功能實際上很簡單。每個 PIC 有 8 個輸入線,稱為中斷請求 (IRQ),編號從 0 到 7。當這些線之一變為高電平時,PIC 會提醒 CPU 併發送相應的中斷號。這個數字是透過將 IRQ 編號 (0 到 7) 加到內部 "向量偏移" 值來計算的。CPU 使用這個值來執行相應的中斷服務例程。(有關更多資訊,請參閱 高階中斷)。

當然,這並不像看起來那麼簡單,因為每個系統都有兩個 PIC,一個 "主" 和一個 "從"。所以,當從機發出中斷時,它實際上是傳送到主機的,主機再將它傳送到 CPU。這樣,中斷就會級聯,處理器可以有 16 個 IRQ 線。在這 16 個 IRQ 線中,有一個是用於兩個 PIC 晶片相互通訊的,因此可用 IRQ 的數量減少到 15 個。

雖然 cli 和 sti 可用於停用和啟用 *所有* 硬體中斷,但有時需要有選擇地停用來自某些裝置的中斷。為此,PIC 有一個內部 8 位暫存器,稱為中斷遮蔽暫存器 (IMR)。該暫存器中的位決定哪些 IRQ 傳遞到 CPU。如果一個 IRQ 被觸發,但 IMR 中的對應位被設定,則它會被忽略,不會發送任何內容到 CPU。

在 15 個可用的 IRQ 中,一些與一種型別的裝置普遍相關聯

  • IRQ 0 ‒ 系統定時器
  • IRQ 1 — 鍵盤控制器
  • IRQ 3 — 序列埠 COM2
  • IRQ 4 — 序列埠 COM1
  • IRQ 5 — 行式列印終端 2
  • IRQ 6 — 軟盤控制器
  • IRQ 7 — 行式列印終端 1
  • IRQ 8 — RTC 定時器
  • IRQ 9 - X86_Assembly/ACPI
  • IRQ 12 — 滑鼠控制器
  • IRQ 13 — 數學協處理器
  • IRQ 14 — ATA 通道 1
  • IRQ 15 — ATA 通道 2

程式設計

[編輯 | 編輯原始碼]

系統中的兩個 PIC 各自分配一個命令埠和一個數據埠

PIC1 PIC2
命令 0x20 0xA0
資料 0x21 0xA1

通常,從資料埠讀取會返回 IMR 暫存器(見上文),寫入到它會設定該暫存器。我們可以利用這一點來設定哪些 IRQ 應該被忽略。例如,要停用 IRQ 6(軟盤控制器)觸發

in ax, 0x21
or ax, (1 << 6)
out 0x21, ax

同樣,要停用 IRQ 12(滑鼠控制器)

in ax, 0xA1
or ax, (1 << 4)   ;IRQ 12 is actually IRQ 4 of PIC2
out 0xA1, ax

重對映

[編輯 | 編輯原始碼]

另一個常見任務,通常在作業系統初始化期間執行,是重對映 PIC。也就是說,改變它們的內部向量偏移量,從而改變它們傳送的中斷號。PIC1 的初始向量偏移量為 8,因此它會觸發中斷號 8 到 15。不幸的是,低 32 箇中斷中的一些被 CPU 用於異常(除零、頁面錯誤等),導致硬體中斷和軟體中斷之間發生衝突。對此的通常解決方案是將 PIC1 重對映到從 32 開始,並且通常將 PIC2 緊隨其後從 40 開始。這需要完全重新啟動 PIC,但實際上並不困難,只需八個 out 即可完成。

mov al, 0x11
out 0x20, al     ;restart PIC1
out 0xA0, al     ;restart PIC2

mov al, 0x20
out 0x21, al     ;PIC1 now starts at 32
mov al, 0x28
out 0xA1, al     ;PIC2 now starts at 40

mov al, 0x04
out 0x21, al     ;setup cascading
mov al, 0x02
out 0xA1, al

mov al, 0x01
out 0x21, al
out 0xA1, al     ;done!
華夏公益教科書