下面给出一个用于模拟异常和演示异常处理的实例。该实例的逻辑功能是,在屏幕上显示一条提示用户以按键方式选择异常类型的字符,然后模拟指定的异常。该实例演示内容包括:除法出错故障处理、溢出陷阱处理、段不存在故障处理、堆栈段出错处理和通用保护故障处理;还有作为一个独立任务方式出现的陷阱处理程序。
1.源程序组织和清单
为了演示以独立任务方式出现的陷阱处理程序,实例含有两个任务:演示任务和读键盘任务。实例由如下几部分组成:
(1)全局描述符表GDT和中断描述符表IDT;
(2)读键盘任务局部描述符表、任务状态段、堆栈段和代码段等;
(3)演示任务的局部描述符表、任务状态段、堆栈段、代码段和数据段等;
(4)作为演示任务一部分的有关陷阱处理和故障处理程序的代码段;
(5)作为演示任务一部分的显示出错码过程的代码段;
(6)实模式下执行的启动和结束程序代码段和数据段。
在切换到保护模式后,就进入临时代码段。为了简单,演示任务不发生特权级变换。演示步骤如下:
(1)从临时代码段转移到演示代码段。
(2)做演示准备。把演示任务的LDT选择子装入LDTR,并填入TSS,装载任务寄存器TR,建立演示任务堆栈,设置其它数据段寄存器。
(3)接收要模拟的异常类型号。通过软中断指令INT调用读键盘任务完成该步骤。读键盘任务只有在接收到指定的字符后才结束。接收的字符是0、4、B、C和D。
按接收的字符模拟异常。即根据键入的字符,执行有关程序片段。在这些片段中,有意安排了能引起有关故障或陷阱的指令。
结束演示,转临时代码段,返回DOS。
程序清单如下:
名称:ASM7.ASM
功能:模拟异常和演示异常处理
编译:TASM ASM7.ASM
连接:TLINK ASM7.OBJ
----------------------------------------------------------------------------
INCLUDE 386SCD.INC
----------------------------------------------------------------------------
GDTSeg SEGMENT PARA USE16 全局描述符表数据段(16位)
----------------------------------------------------------------------------
全局描述符表GDT
GDT LABEL BYTE
空描述符
DUMMY Desc <>
规范段描述符及选择子
Normal Desc <0ffffh,,,ATDW,,>
Normal_Sel = Normal-GDT
视频缓冲区段描述符(DPL=3)及选择子
VideoBuf Desc <0ffffh,8000h,0bh,ATDW,,>
VideoBuf_Sel = VideoBuf-GDT
----------------------------------------------------------------------------
EFFGDT LABEL BYTE
临时代码段描述符及选择子
TempCode Desc <0ffffh,TempCodeSeg,,ATCE,,>
TempCode_Sel = TempCode-GDT
演示代码段描述符及选择子
DemoCode Desc
DemoCode_Sel = DemoCode-GDT
演示任务局部描述符表段描述符及选择子
DemoLDT Desc
DemoLDT_Sel = DemoLDT-GDT
演示任务TSS段描述符及选择子
DemoTSS Desc
DemoTSS_Sel = DemoTSS-GDT
缓冲数据段描述符及选择子
XBuffer Desc
XBuffer_Sel = XBuffer-GDT
读键盘任务局部描述符表段描述符及选择子
GKeyLDT Desc
GKeyLDT_Sel = GKeyLDT-GDT
读键盘任务TSS段描述符及选择子
GKeyTSS Desc
GKeyTSS_Sel = GKeyTSS-GDT
显示陷阱处理程序代码段描述符及选择子
EchoCode Desc
EchoCode_Sel = EchoCode-GDT
显示出错码过程代码段描述符及选择子
SubCode Desc
SubCode_Sel = SubCode-GDT
其它中断或异常处理程序代码段描述符及选择子
Other Desc
Other_Sel = Other-GDT
----------------------------------------------------------------------------
GDTLen = $-GDT 全局描述符表长度
GDNum = ($-EFFGDT)/(SIZE Desc) 需处理基地址的描述符个数
----------------------------------------------------------------------------
GDTSeg ENDS 全局描述符表段定义结束
----------------------------------------------------------------------------
IDTSeg SEGMENT PARA USE16 中断描述符表数据段(16位)
----------------------------------------------------------------------------
IDT LABEL BYTE 中断描述符表
0号陷阱门描述符(对应除法出错故障)
Gate
从1--3的3个陷阱门描述符
REPT 3
Gate
ENDM
4号陷阱门描述符(对应溢出陷阱)
Gate
从5--0ah的的6个陷阱门描述符
REPT 6
Gate
ENDM
0bh号陷阱门描述符(对应段不存在故障)
Gate
0ch号陷阱门描述符(对应堆栈段故障)
Gate
0dh号陷阱门描述符(对应通用保护故障)
Gate
从0eh--0edh的240个陷阱门描述符
REPT 240
Gate
ENDM
对应0feh号陷阱门描述符(对应显示中断处理程序)
Gate
0ffh号任务门描述符(对应读键盘中断处理任务)
Gate <,GKeyTSS_Sel,,ATTaskGate,>
----------------------------------------------------------------------------
IDTLen = $-IDT
----------------------------------------------------------------------------
IDTSeg ENDS 中断描述符表段定义结束
----------------------------------------------------------------------------
读键盘任务局部描述符表段
----------------------------------------------------------------------------
GKeyLDTSeg SEGMENT PARA USE16
----------------------------------------------------------------------------
GLDT LABEL BYTE
代码段描述符及选择子
GKeyCode Desc <0ffffh,GKeyCodeSeg,,ATCE,,>
GKeyCode_Sel = GKeyCode-GLDT+TIL
堆栈段描述符及选择子
GKeyStack Desc
GKeyStack_Sel = GKeyStack-GLDT+TIL
----------------------------------------------------------------------------
GKeyLDNum = ($-GLDT)/(SIZE Desc) 需初始化基地址的描述符个数
GKeyLDTLen = $ 局部描述符表段长度
----------------------------------------------------------------------------
GKeyLDTSeg ENDS
----------------------------------------------------------------------------
读键盘任务TSS段
----------------------------------------------------------------------------
GKeyTSSSeg SEGMENT PARA USE16
DD 0 链接字
DD ? 0级堆栈指针
DW ?,?
DD ? 1级堆栈指针
DW ?,?
DD ? 2级堆栈指针
DW ?,?
DD 0 CR3
DW GKeyBegin,0 EIP
DD 0 EFLAGS
DD 0 EAX
DD 0 ECX
DD 0 EDX
DD 0 EBX
DW GKeyStackLen,0 ESP
DD 0 EBP
DD 0 ESI
DD 0 EDI
DW Normal_Sel,0 ES
DW GKeyCode_Sel,0 CS
DW