📄 asm7.asm
字号:
;名称: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 <DemoCodeLen-1,DemoCodeSeg,,ATCE,,>
DemoCode_Sel = DemoCode-GDT
;演示任务局部描述符表段描述符及选择子
DemoLDT Desc <DemoLDTLen-1,DemoLDTSeg,,ATLDT,,>
DemoLDT_Sel = DemoLDT-GDT
;演示任务TSS段描述符及选择子
DemoTSS Desc <DemoTSSLen-1,DemoTSSSeg,,AT386TSS,,>
DemoTSS_Sel = DemoTSS-GDT
;缓冲数据段描述符及选择子
XBuffer Desc <BufferLen-1,BufferSeg,,ATDW,,>
XBuffer_Sel = XBuffer-GDT
;读键盘任务局部描述符表段描述符及选择子
GKeyLDT Desc <GKeyLDTLen-1,GKeyLDTSeg,,ATLDT,,>
GKeyLDT_Sel = GKeyLDT-GDT
;读键盘任务TSS段描述符及选择子
GKeyTSS Desc <GKeyTSSLen-1,GKeyTSSSeg,,AT386TSS,,>
GKeyTSS_Sel = GKeyTSS-GDT
;显示陷阱处理程序代码段描述符及选择子
EchoCode Desc <EchoCodeLen-1,EchoCodeSeg,,ATCE,,>
EchoCode_Sel = EchoCode-GDT
;显示出错码过程代码段描述符及选择子
SubCode Desc <SubCodeLen-1,SubCodeSeg,,ATCE,,>
SubCode_Sel = SubCode-GDT
;其它中断或异常处理程序代码段描述符及选择子
Other Desc <OtherCodeLen-1,OtherCodeSeg,,ATCE,,>
Other_Sel = Other-GDT
;----------------------------------------------------------------------------
GDTLen = $-GDT ;全局描述符表长度
GDNum = ($-EFFGDT)/(SIZE Desc) ;需处理基地址的描述符个数
;----------------------------------------------------------------------------
GDTSeg ENDS ;全局描述符表段定义结束
;----------------------------------------------------------------------------
IDTSeg SEGMENT PARA USE16 ;中断描述符表数据段(16位)
;----------------------------------------------------------------------------
IDT LABEL BYTE ;中断描述符表
;0号陷阱门描述符(对应除法出错故障)
Gate <DivBegin,Divide_Sel,,AT386TGate,>
;从1--3的3个陷阱门描述符
REPT 3
Gate <OtherBegin,Other_Sel,,AT386TGate,>
ENDM
;4号陷阱门描述符(对应溢出陷阱)
Gate <OFBegin,OF_Sel,,AT386TGate,>
;从5--0ah的的6个陷阱门描述符
REPT 6
Gate <OtherBegin,Other_Sel,,AT386TGate,>
ENDM
;0bh号陷阱门描述符(对应段不存在故障)
Gate <SNPBegin,SNP_Sel,,AT386TGate,>
;0ch号陷阱门描述符(对应堆栈段故障)
Gate <SSEBegin,SSE_Sel,,AT386TGate,>
;0dh号陷阱门描述符(对应通用保护故障)
Gate <GPBegin,GP_Sel,,AT386TGate,>
;从0eh--0edh的240个陷阱门描述符
REPT 240
Gate <OtherBegin,Other_Sel,,AT386TGate,>
ENDM
;对应0feh号陷阱门描述符(对应显示中断处理程序)
Gate <EchoBegin,EchoCode_Sel,,AT386TGate,>
;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 <GKeyStackLen-1,GKeyStackSeg,,ATDWA,,>
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 GKeyStack_Sel,0 ;SS
DW Normal_Sel,0 ;DS
DW Normal_Sel,0 ;FS
DW Normal_Sel,0 ;GS
DW GKeyLDT_Sel,0 ;LDTR
DW 0 ;调试陷阱标志
DW $+2 ;指向I/O许可位图的偏移
DB 0ffh ;I/O许可位图结束字节
GKeyTSSLen = $
GKeyTSSSeg ENDS
;----------------------------------------------------------------------------
;读键盘任务堆栈段
;----------------------------------------------------------------------------
GKeyStackSeg SEGMENT PARA USE16
GKeyStackLen = 1024
DB GKeyStackLen DUP(0)
GKeyStackSeg ENDS
;----------------------------------------------------------------------------
;读键盘任务代码段
;----------------------------------------------------------------------------
GKeyCodeSeg SEGMENT PARA USE16
ASSUME CS:GKeyCodeSeg,DS:RDataSeg,ES:BufferSeg
;----------------------------------------------------------------------------
GKeyBegin PROC FAR
push ds
push es
push fs
push gs
mov ax,Normal_Sel
mov ss,ax ;准备转实方式
mov eax,cr0
and al,11111110b
mov cr0,eax ;转实方式
JUMP16 <SEG GetKey>,<OFFSET GetKey>
GetKey: mov ax,RDataSeg ;实方式
mov ds,ax
mov ebp,esp ;恢复实方式部分现场
lss sp,DWORD PTR SPVar
lidt QWORD PTR NORVIDTR
sti
mov dx,OFFSET Mess
mov ah,9
int 21h ;显示提示信息
GetKey1: mov ah,0
int 16h ;读键盘
cmp al,'0'
jz GetKey2
cmp al,'4'
jz GetKey2
and al,11011111b ;小写转大写
cmp al,'B'
jb GetKey1
cmp al,'D'
ja GetKey1 ;只有[0,4,b,c,d]有效
GetKey2: mov dl,al
mov ah,2
int 21h ;显示所按字符
mov ax,BufferSeg
mov es,ax
mov BYTE PTR es:KeyASCII,dl ;保存到缓冲数据段
cli ;准备返回保护方式
lidt QWORD PTR VIDTR
mov eax,cr0
or al,1
mov cr0,eax
JUMP16 <GKeyCode_Sel>,<OFFSET GetKeyV>
GetKeyV: mov ax,GKeyStack_Sel ;又进入保护方式
mov ss,ax
mov esp,ebp
pop gs
pop fs
pop es
pop ds
iretd
jmp GKeyBegin
GKeyBegin ENDP
;----------------------------------------------------------------------------
GKeyCodeLen = $
GKeyCodeSeg ENDS
;----------------------------------------------------------------------------
;其它中断或异常处理程序的代码段
;----------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -