程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> 匯編語言 >> 演示中斷處理的實例(實例六)

演示中斷處理的實例(實例六)

編輯:匯編語言

下面給出一個用於演示中斷處理的實例。該實例的邏輯功能是,在屏幕的左上角以倒計時方式顯示秒為單位的時間,在時間用完後結束。該實例演示內容包括:外部中斷處理程序和陷阱處理程序。

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位)
;----------------------------------------------------------------------------
        ;全局描述符表GDT
GDT       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
        ASSUMEGISter>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 USE16
Count      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 USE16
Mess      DB   '8',4eh
EchoDataLen   =    $
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
        iretd
EchoBegin    ENDP
;----------------------------------------------------------------------------
EchoCodeLen   =    $
EchoCodeSeg   ENDS
;----------------------------------------------------------------------------
;演示任務的堆棧段
;----------------------------------------------------------------------------
DemoStackSeg  SEGMENT PARA USE16
DemoStackLen  =    1024
        DB   DemoStackLen DUP(0)
DemoStackSeg  ENDS
;----------------------------------------------------------------------------
;演示任務的數據段
;----------------------------------------------------------------------------
DemoDataSeg   SEGMENT PARA USE16
Flag      DB   0
DemoDataLen   =    $
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   ?             ;用於保存實方式下的SP
SSVar      DW   ?             ;用於保存實方式下的SS
IMaskRegV    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   21h
Start      ENDP
;----------------------------------------------------------------------------
InitGDT     PROC
        push  ds
        mov   ax,GDTSeg
        mov   ds,ax
        mov   cx,GDNum
        mov   si,OFFSET EFFGDT
InitG:     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
        ret
InitGDT     ENDP
;----------------------------------------------------------------------------
InitIDT     PROC
        mov   bx,16
        mov   ax,IDTSeg
        mul   bx
        mov   WORD PTR VIDTR.Base,ax
        mov   WORD PTR VIDTR.Base+2,dx
        ret
InitIDT     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指令作詳細說明。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved