| 网站首页 | JAVA文章 | AppServers | Web开发 | 应用开发 | 资源下载 | 论坛
    想学好编程,学好外语很重要  [enadd  2006年12月25日]        
设为首页 加入收藏 联系站长
您现在的位置: 编程笔记网 >> 应用开发 >> 汇编语言 >> 汇编文档 >> 文章正文
演示中断处理的实例(实例六)            【字体:
演示中断处理的实例(实例六)
作者:-    文章来源:互连网    点击数:    更新时间:2007-1-20

演示中断处理的实例(实例六):    下面给出一个用于演示中断处理的实例。该实例的逻辑功能是,在屏幕的左上角以倒计时方式显示秒为单位的时间,在时间用完后结束。该实例演示内容包括:外部中断处理程序和陷阱处理程序。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位);---------------------------------------------------------------------------- ;全局描述符表GDTGDT 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 USE16Count 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 USE16Mess DB '8',4ehEchoDataLen = $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 iretdEchoBegin ENDP;----------------------------------------------------------------------------EchoCodeLen = $EchoCodeSeg ENDS;----------------------------------------------------------------------------;演示任务的堆栈段;----------------------------------------------------------------------------DemoStackSeg SEGMENT PARA USE16DemoStackLen = 1024 DB DemoStackLen DUP(0)DemoStackSeg ENDS;----------------------------------------------------------------------------;演示任务的数据段;----------------------------------------------------------------------------DemoDataSeg SEGMENT PARA USE16Flag DB 0DemoDataLen = $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 ? ;用于保存实方式下的SPSSVar DW ? ;用于保存实方式下的SSIMaskRegV 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 21hStart ENDP;----------------------------------------------------------------------------InitGDT PROC push ds mov ax,GDTSeg mov ds,ax mov cx,GDNum mov si,OFFSET EFFGDTInitG: 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 retInitGDT ENDP;----------------------------------------------------------------------------InitIDT PROC mov bx,16 mov ax,IDTSeg mul bx mov WORD PTR VIDTR.Base,ax mov WORD PTR VIDTR.Base+2,dx retInitIDT ENDP;----------------------------------------------------------------------------RCodeSeg ENDS END Start2.关于实例六的说明(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] [3] [4] [5] [6] 下一页  

文章录入:enadd    责任编辑:enadd 
  • 上一篇文章:

  • 下一篇文章:
  • 发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
    最新热点 最新推荐 相关文章
  • 基本概念(win32)汇编教程

  • win32消息框

  • 创建简单的窗口

  • 绘制文本

  • 处理键盘输入消息

  • 处理键盘输入消息

  • 菜单

  • 子窗口控件

  • DeviceIoControl接口

  • 进一步学习对话框

  •   网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)
    | 设为首页 | 加入收藏 | 联系站长 | 友情链接 | 版权申明 | 管理登录 |