2007年10月13日 星期六

OrzMicrokernel bit32.asm 進入保護模式後的核心初始化

Standard
OrzMicrokernel 在 bit16.asm 完成了轉換成保護模式的工作,緊接著會跳到 bit32.asm 初始化核心和設定硬體中斷周期。最重要的是,從跳轉到這檔案後,就可以開始使用 32 位元的各種延伸暫存器以及更大的記憶體定址,但前題是:我們得先將新的暫存器區段位址設定好,因為暫存器設定還是處於在真實模式時的狀態。

程式碼和詳細註解:
[BITS 32]
; Intel 處理器的設計是以 dword 為單位來存取記憶體,所以記憶體位址定為 4 的倍數。
align 4 ; 設定所有資料的起始位址都是 4 的倍數
Begin32c:
; 初始化暫存器區段
mov ax, kernel_data - _GDT ; 從 tables.asm 的 kernel_data 開始
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov esp, 0x2FFFF ; 堆疊暫存器設在 2MB 記憶體後

call TestMemory ; 呼叫 mm.asm 的子程式測試記憶體

mov edi, memMap ; 初始化索引暫存器
;
memMap 記憶體大小有0x20000=128KB
mov ecx, 0x100 / 32 ; 計數器設為 256/32=8
xor eax, eax ; 將 eax 歸零
dec eax
rep stosd ; 每次從 EAX 中複製 4 Bytes 到 EDI
; 複製 8 次


mov ecx, 0x20000 / 4 - (0x100 / 32) ; 計數器設為 32760
xor eax,eax ; 將 eax 歸零
rep stosd ; 每次從 EAX 中複製 4 Bytes 到 EDI
; 複製 32760 次


; 設定 825x 計時器
; 模式控制暫存器(I/O 埠編號 43H):共 8 位元
;
; 位元 位元值 說明
; 0 0 使用二進位格式的數值
; 1 使用 BCD 格式的數值
; 1,2,3 000 計時模式 0
; 001 計時模式 1
; 010 計時模式 2
; 011 計時模式 3
; 100 計時模式 4
; 101 計時模式 5
; 4,5 00 保留住目前數值
; 01 僅讀寫較高的位元組
; 10 僅讀寫較低的位元組
; 11 先讀寫較低的位元組,再讀寫較高的位元組
; 7,6 00 選擇計時通道 0
; 01 選擇計時通道 1
; 10 選擇計時通道 2
; 11 指定讀回命令
mov al, 0x34 ; 設定計時器
; 設定值為 00110100:
; 使用二進位格式的數值
; 計時模式 2
; 先讀寫較低的位元組,再讀寫較高的位元組
; 選擇計時通道 0
out 0x43, al ; 設定 AL 至模式控制暫存器

; 設定時間周期為 10ms(100Hz)
; 即每 10ms 產生一次中斷信號
; 設定值算法:1193180 / 100 = 11931 = 0x2e9b
; 石英震盪器每秒震盪 1193180 次
; 頻率 100Hz
mov al, 0x9b ; 先設定低位元 0x9b
out 0x40, al ; 輸入到計時器0
mov al, 0x2e ; 再設定高位元 0x2e
out 0x40, al ; 輸入到計時器0

call EnableIRQs ; 呼叫 irqs.asm 的子程式以啟動 IRQ 機制



後記

這次比較特別的部份,就是牽扯到 Timer 的操作,我想應該只有少數的 Programer 有機會直接接觸到 825x 計時器,我們過去還得靠它才能讓 PC Speaker 發出難聽的電子旋律呢!(笑)