WEB开发网
开发学院软件开发汇编语言 演示中断处理的实例(实例六) 阅读

演示中断处理的实例(实例六)

 2009-10-12 09:36:35 来源:WEB开发网   
核心提示:源程序清单如下:;名称:ASM6.ASM;功能:演示中断处理的实现;编译:TASM ASM6.ASM;连接:TLINK ASM6.OBJ;INCLUDE 386SCD.INC;;部分常量定义;EOICOM= 20h ;外部中断处理结束命令ICREGP= 20h ;中断控制寄存器端口地址IMREGP= 21h ;中断屏蔽

源程序清单如下:

;名称: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

Tags:演示 中断 处理

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接