网站首页  |  幼儿教育  |  中小学教育  |  电脑教育  |  英语教育  |  教育论文  |  家长教育 设为首页加入收藏联系投稿 
 位置: 中国教育学习网 > 电脑教育 > 程序设计 > 汇编语言 > 正文

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

字号:   

    下面给出一个用于演示中断处理的实例。该实例的逻辑功能是,在屏幕的左上角以倒计时方式显 示秒为单位的时间,在时间用完后结束。该实例演示内容包括:外部中断处理程序和陷阱处理程序。

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

                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 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指令作详细说明。
收藏此文  |  打印 查看:  

 
  • 上一篇教程:

  • 下一篇教程: 没有了

  •   GoogLe
     
      最新推荐
  • 此栏目下没有推荐教程

  •   关注热点

      GoogLe

     
    Powered by Cn-Education.Com (c) 2005-2008 中国教育学习网 教育网站长QQ交流群60041790
    设为首页  |  加入收藏  |  版权申明  |  广告服务  |  联系我们  |  友情链接  |  网站地图  |  返回顶部 ↑