演示中斷處理的例項(例項六)(轉)

heying1229發表於2007-07-28
斷處理的例項(例項六):
下面給出一個用於演示中斷處理的例項。該例項的邏輯功能是,在螢幕的左上角以倒數計時方式顯示秒為單位的時間,在時間用完後結束。該例項演示內容包括:外部中斷處理程式和陷阱處理程式。

1.源程式組織和清單

本例項由如下幾部分組成:
(1)全域性描述符表GDT。GDT中除了含有常見的幾個描述符外,還含有描述時鐘中斷處理程式所使用的程式碼段和資料段描述符,以及描述顯示程式所使用的程式碼段和資料段描述符。
(2)中斷描述符表IDT。為了在保護模式下響應中斷和處理異常,必須有IDT。IDT含有256個門描述符。8號安排的是一個通向時鐘中斷處理程式的中斷門,0FEH號安排的是通向顯示處理程式的陷阱門,其它均安排成通向其它中斷或異常處理程式的陷阱門。
(3)時鐘中斷處理程式的程式碼段和資料段。
(4)實現直接寫顯示緩衝區進行顯示的程式程式碼段和資料段。
(5)處理其它中斷或異常的處理程式的程式碼段。
(6)演示程式的程式碼段、資料段和堆疊段。
(7)真實模式下執行的啟動和結束程式程式碼段和資料段。
源程式清單如下:
;名稱:ASM6.ASM;功能:演示中斷處理的實現;編譯:TASM ASM6.ASM;連線:TLINK ASM6.OBJ;----------------------------------------------------------------------------INCLUDE         386SCD.INC;----------------------------------------------------------------------------;部分常量定義;----------------------------------------------------------------------------EOICOM          =       20h                       ;外部中斷處理結束命令ICREGP          =       20h                       ;中斷控制暫存器埠地址IMREGP          =       21h                       ;中斷遮蔽暫存器埠地址;----------------------------------------------------------------------------GDTSeg          SEGMENT PARA USE16                ;全域性描述符表資料段(16位);----------------------------------------------------------------------------                ;全域性描述符表GDTGDT             LABEL   BYTE                ;空描述符DUMMY           Desc    <>                ;規範段描述符Normal          Desc    <0ffffh,,,ATDW,,>                ;影片緩衝區段描述符(DPL=3)VideoBuf        Desc    <0ffffh,8000h,0bh,ATDW,,>;----------------------------------------------------------------------------EFFGDT          LABEL   BYTE                ;臨時程式碼段描述符TempCode        Desc    <0ffffh,TempCodeSeg,,ATCE,,>                ;演示程式碼段描述符DemoCode        Desc    <DemoCodeLen-1,DemoCodeSeg,,ATCE,,>                ;演示資料段描述符DemoData        Desc    <DemoDataLen-1,DemoDataSeg,,ATDW,,>                ;演示堆疊段描述符DemoStack       Desc    <DemoStackLen-1,DemoStackSeg,,ATDWA,,>                ;0feh號中斷處理程式(顯示程式)程式碼段描述符EchoCode        Desc    <EchoCodeLen-1,EchoCodeSeg,,ATCE,,>                ;0feh號中斷處理程式(顯示程式)資料段描述符EchoData        Desc    <EchoDataLen-1,EchoDataSeg,,ATDW,,>                ;8號中斷處理程式程式碼段描述符TICode          Desc    <TICodeLen-1,TICodeSeg,,ATCE,,>                ;8號中斷處理程式資料段描述符TIData          Desc    <TIDataLen-1,TIDataSeg,,ATDW,,>                ;其它中斷或異常處理程式程式碼段描述符Other           Desc    <OtherCodeLen-1,OtherCodeSeg,,ATCE,,>;----------------------------------------------------------------------------GDTLen          =       $-GDT                     ;全域性描述符表長度GDNum           =       ($-EFFGDT)/(SIZE Desc)    ;需特殊處理的描述符數;----------------------------------------------------------------------------Normal_Sel      =       Normal-GDT                ;規範段描述符選擇子Video_Sel       =       VideoBuf-GDT              ;影片緩衝區段描述符選擇子;----------------------------------------------------------------------------TempCode_Sel    =       TempCode-GDT              ;臨時程式碼段的選擇子DemoCode_Sel    =       DemoCode-GDT              ;演示程式碼段的選擇子DemoData_Sel    =       DemoData-GDT              ;演示資料段的選擇子DemoStack_Sel   =       DemoStack-GDT             ;演示堆疊段的選擇子EchoCode_Sel    =       EchoCode-GDT              ;0feh號中斷程式程式碼段選擇子EchoData_Sel    =       EchoData-GDT              ;0feh號中斷程式資料段選擇子TICode_Sel      =       TICode-GDT                ;8號中斷程式程式碼段選擇子TIData_Sel      =       TIData-GDT                ;8號中斷程式資料段選擇子Other_Sel       =       Other-GDT                 ;其它中斷或異常程式碼段選擇子;----------------------------------------------------------------------------GDTSeg          ENDS                              ;全域性描述符表段定義結束;----------------------------------------------------------------------------IDTSeg          SEGMENT PARA USE16                ;中斷描述符表資料段(16位);----------------------------------------------------------------------------IDT             LABEL   BYTE                      ;中斷描述符表                ;0--7的8個陷阱門描述符                REPT    8                Gate    <OtherBegin,Other_Sel,,AT386TGate,>                ENDM                ;對應8號(時鐘)中斷處理程式的門描述符                Gate    <TIBegin,TICode_Sel,,AT386IGate,>                ;從9--0fdh的245個陷阱門描述符                REPT    245                Gate    <OtherBegin,Other_Sel,,AT386TGate,>                ENDM                ;對應0feh號中斷處理程式的陷阱門描述符                Gate    <EchoBegin,EchoCode_Sel,,AT386TGate,>                ;對應0ffh號中斷處理程式的陷阱門描述符                Gate    <OtherBegin,Other_Sel,,AT386TGate,>;----------------------------------------------------------------------------IDTLen          =       $-IDT;----------------------------------------------------------------------------IDTSeg          ENDS                              ;中斷描述符表段定義結束;----------------------------------------------------------------------------;其它中斷或異常處理程式的程式碼段;----------------------------------------------------------------------------OtherCodeSeg    SEGMENT PARA USE16                ASSUME  CS:OtherCodeSeg;----------------------------------------------------------------------------OtherBegin      PROC    FAR                mov     ax,Video_Sel                mov     es,ax                mov     ah,17h                    ;在螢幕左上角顯示蘭底白字                mov     al,'!'                    ;符號"!"                mov     WORD PTR es:[0],ax                jmp     $                         ;無限迴圈OtherBegin      ENDP;----------------------------------------------------------------------------OtherCodeLen    =       $OtherCodeSeg    ENDS;----------------------------------------------------------------------------;8號中斷處理程式的資料段;----------------------------------------------------------------------------TIDataSeg       SEGMENT PARA USE16Count           DB      0                         ;中斷髮生的計數器TIDataLen       =       $TIDataSeg       ENDS;----------------------------------------------------------------------------;8號中斷處理程式的程式碼段;----------------------------------------------------------------------------TICodeSeg       SEGMENT PARA USE16                ASSUME  CS:TICodeSeg,DS:TIDataSeg;----------------------------------------------------------------------------TIBegin         PROC    FAR                push    eax                       ;保護現場                push    ds                push    fs                push    gs                mov     ax,TIData_Sel             ;置中斷處理程式資料段                mov     ds,ax                mov     ax,EchoData_Sel           ;置顯示過程資料段                mov     fs,ax                mov     ax,DemoData_Sel           ;置演示程式資料段                mov     gs,ax                cmp     Count,0                jnz     TI2                       ;計數非0表示未到1秒                mov     Count,18                  ;每秒約18次                int     0feh                      ;呼叫0FEH號中斷處理程式顯示                cmp     BYTE PTR fs:Mess,'0'                jnz     TI1                mov     BYTE PTR gs:Flag,1        ;顯示符號'0'時置標記TI1:            dec     BYTE PTR fs:Mess          ;調整顯示符號TI2:            dec     Count                     ;調整計數                pop     gs                        ;恢復現場                pop     fs                pop     ds                mov     al,EOICOM                 ;通知中斷控制器中斷處理結束                out     ICREGP,al                pop     eax                iretd                             ;中斷返回TIBegin         ENDP;----------------------------------------------------------------------------TICodeLen       =       $TICodeSeg       ENDS;----------------------------------------------------------------------------;0FEH號中斷處理程式資料段;----------------------------------------------------------------------------EchoDataSeg     SEGMENT PARA USE16Mess            DB      '8',4ehEchoDataLen     =       $EchoDataSeg     ENDS;----------------------------------------------------------------------------;0FEH號中斷處理程式(顯示程式)的程式碼段;----------------------------------------------------------------------------EchoCodeSeg     SEGMENT PARA USE16                ASSUME  CS:EchoCodeSeg,DS:EchoDataSeg;----------------------------------------------------------------------------EchoBegin       PROC    FAR                push    ax                        ;保護現場                push    ds                push    es                mov     ax,EchoData_Sel           ;置顯示過程資料段                mov     ds,ax                mov     ax,Video_Sel              ;置影片緩衝區資料段                mov     es,ax                mov     ax,WORD PTR Mess                mov     WORD PTR es:[0],ax                pop     es                pop     ds                pop     ax                iretdEchoBegin       ENDP;----------------------------------------------------------------------------EchoCodeLen     =       $EchoCodeSeg     ENDS;----------------------------------------------------------------------------;演示任務的堆疊段;----------------------------------------------------------------------------DemoStackSeg    SEGMENT PARA USE16DemoStackLen    =       1024                DB      DemoStackLen DUP(0)DemoStackSeg    ENDS;----------------------------------------------------------------------------;演示任務的資料段;----------------------------------------------------------------------------DemoDataSeg     SEGMENT PARA USE16Flag            DB      0DemoDataLen     =       $DemoDataSeg     ENDS;----------------------------------------------------------------------------;演示任務的程式碼段;----------------------------------------------------------------------------DemoCodeSeg     SEGMENT PARA USE16                ASSUME  CS:DemoCodeSeg,DS:DemoDataSeg;----------------------------------------------------------------------------DemoBegin       PROC    FAR                mov     ax,DemoStack_Sel          ;置堆疊                mov     ss,ax                mov     sp,DemoStackLen           ;置資料段                mov     ax,DemoData_Sel                mov     ds,ax                mov     es,ax                mov     fs,ax                mov     gs,ax                mov     al,11111110b              ;置中斷遮蔽字                out     IMREGP,al                 ;只開發時鐘中斷                sti                               ;開中斷DemoConti:      cmp     BYTE PTR Flag,0           ;判標誌                jz      DemoConti                 ;直到不為0                cli                               ;關中斷                ;轉回臨時程式碼段,準備回實方式                JUMP16  TempCode_Sel,<OFFSET ToDos>DemoBegin       ENDP;----------------------------------------------------------------------------DemoCodeLen     =       $DemoCodeSeg     ENDS;----------------------------------------------------------------------------TempCodeSeg     SEGMENT PARA USE16                ;臨時任務的程式碼段                ASSUME  CS:TempCodeSeg;----------------------------------------------------------------------------Virtual         PROC    FAR                JUMP16  DemoCode_Sel,DemoBegin    ;轉演示任務ToDos:          mov     ax,Normal_Sel             ;恢復實方式段描述符快取記憶體                mov     ds,ax                mov     es,ax                mov     fs,ax                mov     gs,ax                mov     ss,ax                mov     eax,cr0                   ;準備返回真實模式                and     al,11111110b                mov     cr0,eax                JUMP16  <SEG Real>,<OFFSET Real>Virtual         ENDP;----------------------------------------------------------------------------TempCodeSeg     ENDS;============================================================================RDataSeg        SEGMENT PARA USE16                ;實方式資料段VGDTR           PDesc   <GDTLen-1,>               ;GDT偽描述符VIDTR           PDesc   <IDTLen-1,>               ;IDT偽描述符NORVIDTR        PDesc   <3ffh,>                   ;用於儲存原IDTR值SPVar           DW      ?                         ;用於儲存實方式下的SPSSVar           DW      ?                         ;用於儲存實方式下的SSIMaskRegV       DB      ?                         ;用於儲存原中斷遮蔽暫存器值RDataSeg        ENDS;----------------------------------------------------------------------------RCodeSeg        SEGMENT PARA USE16                ;實方式程式碼段                ASSUME  CS:RCodeSeg,DS:RDataSeg;----------------------------------------------------------------------------Start           PROC                mov     ax,RDataSeg                mov     ds,ax                cld                call    InitGDT                   ;初始化全域性描述符表GDT                call    InitIDT                   ;初始化中斷描述符表IDT                mov     SSVar,ss                  ;儲存堆疊指標                mov     SPVar,sp                sidt    QWORD PTR NORVIDTR        ;儲存IDTR                in      al,IMREGP                mov     BYTE PTR IMaskRegV,al                lgdt    QWORD PTR VGDTR           ;裝載GDTR                cli                               ;關中斷                lidt    QWORD PTR VIDTR           ;裝載IDTR                mov     eax,cr0                or      al,1                mov     cr0,eax                JUMP16  <TempCode_Sel>,<OFFSET Virtual>Real:           mov     ax,RDataSeg                mov     ds,ax                lss     sp,DWORD PTR SPVar        ;又回到實方式                lidt    QWORD PTR NORVIDTR                mov     al,IMaskRegV                out     IMREGP,al                sti                mov     ax,4c00h                int     21hStart           ENDP;----------------------------------------------------------------------------InitGDT         PROC                push    ds                mov     ax,GDTSeg                mov     ds,ax                mov     cx,GDNum                mov     si,OFFSET EFFGDTInitG:          mov     ax,[si].BaseL                movzx   eax,ax                shl     eax,4                shld    edx,eax,16                mov     WORD PTR [si].BaseL,ax                mov     BYTE PTR [si].BaseM,dl                mov     BYTE PTR [si].BaseH,dh                add     si,SIZE Desc                loop    InitG                pop     ds                mov     bx,16                mov     ax,GDTSeg                mul     bx                mov     WORD PTR VGDTR.Base,ax                mov     WORD PTR VGDTR.Base+2,dx                retInitGDT         ENDP;----------------------------------------------------------------------------InitIDT         PROC                mov     bx,16                mov     ax,IDTSeg                mul     bx                mov     WORD PTR VIDTR.Base,ax                mov     WORD PTR VIDTR.Base+2,dx                retInitIDT         ENDP;----------------------------------------------------------------------------RCodeSeg        ENDS                END     Start

2.關於例項六的說明

(1)時鐘中斷仍使用8H號中斷向量

為了即簡單又清楚地演示在保護模式下響應外部中斷並進行處理,例項使用了時鐘中斷源,但沒有透過重新設定中斷控制器的方法改變對應的中斷向量。所以,時鐘中斷使用的8H號中斷向量號就與雙重故障異常使用的中斷向量號發生衝突。但例項僅是演示程式,所以只要保證不發生雙重故障異常,就可避免衝突,從而不會影響演示。
設定中斷遮蔽暫存器,僅開放時鐘中斷。所以,在開中斷狀態下,也只可能發生時鐘中斷,而不會發生其它外部中斷。

(2)時鐘中斷處理程式的設計

由於透過中斷門轉時鐘中斷處理程式,所以在控制轉移時不發生任務切換。但外部中斷隨時可能發生,因此中斷處理程式必須採取保護現場等措施。作為演示程式,該中斷處理程式檢查和調整在其資料段中的計數器,滿18次後,就認為已滿一秒,再調整用於顯示的倒計數資訊。如果倒計數資訊為0,那麼就設定演示程式資料段中的時間為0標誌。該中斷處理程式透過約定的資料區與顯示程式及演示程式交換資訊。

(3)利用一個軟中斷(陷阱處理)程式實現顯示

為了演示陷阱及其處理,把顯示過程安排成陷阱處理程式。上述時鐘中斷處理程式透過軟中斷呼叫指令INT呼叫該顯示程式,以顯示倒計數。在控制轉移時,也沒有任務切換。該陷阱處理程式相當於一個“軟中斷”處理程式,類似真實模式下的BIOS中斷INT 10H。

(4)對其它中斷或異常的響應

為了簡單,除了8H號和0FEH號外,IDT中其它的門均通向一個處理程式。該處理程式用於處理其它中斷或異常。處理過程也極其簡單,在螢幕左上角顯示藍底白字的符號“!”,然後進入無限迴圈。實際上,按演示程式現在的安排,不可能發生這種情況。

(5)沒有特權級變換

為了簡單,例項涉及的中斷處理程式和異常處理程式都保持特權級0。所以,控制轉移時不發生特權級變換。因此,沒有使用其它堆疊。

(6)對IDT的初始化

由於IDT中門描述符沒有32位段基地址,並且入口點偏移較小,所以就直接填寫門描述符結構變數,沒有額外再初始化。過程InitIDT只是設定IDT偽描述符。

(7)裝載和儲存IDTR暫存器

再使IDT發揮作用之前,還要裝載中斷描述符表暫存器IDTR;但為了回到真實模式後,恢復原來的IDTR之內容,所以先儲存IDTR的內容。例項使用如下指令儲存IDTR:
    sidt    QWORD PTR NORVIDTR
該指令的功能是把IDTR的內容儲存到儲存器中的偽描述符NORVIDTR中。該偽描述符的結構如前文所述的結構型別PDESC所示,低字是以位元組為單位的界限,高雙字是基地址。在後面的文章中將對SIDT指令作詳細說明。
本例項使用如下指令裝載IDTR暫存器:
    lidt    QWORD PTR VIDTR    lidt    QWORD PTR NORVIDTR
LIDT指令類似於LGDT指令,在後面的文章中將對LIDT指令作詳細說明。
[@more@]

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10172717/viewspace-928727/,如需轉載,請註明出處,否則將追究法律責任。

相關文章