我們目前提供的核心API有個問題,就是每次使用時,需要計算API函數在核心中的位置,一旦核心代碼改變,API接口的位置也會改變,同時調用API的應用程式也必須跟着改變,顯然這種限制是不可接受的。
為了突破目前缺陷,我們必須想出新的API提供辦法。常用的做法是,仿照Linux 将API當做一個中斷調用,由此應用程式在使用API時,隻需要記住API對應的中斷号,然後使用指令int 即可,這樣無論API接口位置如何變動,應用程式的代碼都不需要重新更改。
由此在系統核心的彙編代碼部分做如下修改:
LABEL_IDT:
...
.2DH:
Gate SelectorCode32, AsmConsPutCharHandler,, DA_386IGate
我們在中斷向量表中增加了一個.2D号中斷,該中斷對應的相應函數位址為AsmConsPutCharHandler。
在原來的API接口AsmConsPutChar處增加如下代碼:
asm_cons_putchar:
AsmConsPutCharHandler equ asm_cons_putchar - $$
pushad
push
and eax,
push eax
call cons_putchar
add esp,
popad
iretd
首先我們通過把函數入口位址減去段的起始位址,得到函數相對于代碼段的偏移,這個偏移的值就是AsmConsPutCharHandler, 其次asmConsPutChar一旦調用是,先執行指令pushad, 該指令的作用是把所有通用寄存器壓入堆棧,寄存器跟代碼運作的上下文密切相關,如果在調用中斷時不包含好通用寄存器,那麼從中斷傳回後,由于寄存器的改變,可能會導緻代碼邏輯出現錯誤。在APIZ執行完畢後,執行指令popad,把原先保持起來的寄存器資料重新恢複到對應的寄存器中。
使用中斷提供核心接口調用,應用程式在開發邏輯上可以得到極大的簡化,以下代碼顯示了應用程式如何調用核心API在控制台上顯示字元:
[map symbols hlt.map]
[SECTION .s32]
BITS
mov ax, 'L'
int DH
mov ax, 'G'
int DH
retf
應用程式隻需要把要顯示的字元指派給寄存器ax, 然後出發2d号中斷就可以利用核心導出的API,實作在控制台上輸出字元的功能。同時應用程式無需估計核心代碼修改後,結構API位址會改變的問題,代碼隻需兼顧自身邏輯,于是相比于前一版本的核心調用,邏輯上得到了很大的簡化。
把上面代碼編譯後,在控制台運作hls指令後,效果如下:
更詳實的講解和代碼調試流程,請參看視訊。
更多技術資訊,包括作業系統,編譯器,面試算法,機器學習,人工智能,請關照我的公衆号: