AutoCAD 3DMAX C语言 Pro/E UG JAVA编程 PHP编程 Maya动画 Matlab应用 Android
Photoshop Word Excel flash VB编程 VC编程 Coreldraw SolidWorks A Designer Unity3D
 首页 > 汇编语言

输入/输出保护

51自学网 http://www.51zixue.net
 

2.源程序组织和清单

    为了达到演示目的,实例除了演示任务外,还涉及四个测试任务和一个通用保护故障处理任务。实例由如下几部分组成。
    (1)全局描述符表GDT和中断描述符表IDT;
    (2)其它中断/异常处理程序代码段;
    (3)通用保护故障处理任务的任务状态段、堆栈段和代码段;
    (4)四个测试任务合用的任务状态段、堆栈段和代码段;
    (5)演示任务的任务状态段、堆栈段和代码段;
    (6)演示任务的临时代码段;
    (7)实模式下执行的启动与结束程序代码段和数据段。
    实例九源程序清单如下:
;名称:ASM9.ASM;功能:演示I/O保护及I/O敏感指令的作用;编译:TASM ASM9.ASM;连接:TLINK /32 ASM9.OBJ;----------------------------------------------------------------------------INCLUDE         386SCD.INC;----------------------------------------------------------------------------GDTSeg          SEGMENT PARA USE16                ;全局描述符表段(16位)GDT             LABEL   BYTE                ;空描述符DUMMY           Desc    <>                ;规范段描述符及选择子Normal          Desc    <0ffffh,,,ATDW,,>Normal_Sel      =       Normal-GDT                ;视频缓冲区段描述符(DPL=3)及选择子(任何特权级可写)VideoBuf        Desc    <07fffh,8000h,0bh,ATDW,,>VideoBuf_Sel    =       VideoBuf-GDT;----------------------------------------------------------------------------EFFGDT          LABEL   BYTE                ;演示任务TSS段描述符及选择子DemoTSS         Desc    <DemoTSSLen-1,DemoTSSSeg,,AT386TSS,,>DemoTSS_Sel     =       DemoTSS-GDT                ;演示任务堆栈段描述符及选择子DemoStack       Desc    <DemoStackLen-1,DemoStackSeg,,ATDW,D32,>DemoStack_Sel   =       DemoStack-GDT                ;演示代码段描述符及选择子DemoCode        Desc    <DemoCodeLen-1,DemoCodeSeg,,ATCE,D32,>DemoCode_Sel    =       DemoCode-GDT                ;属于演示任务的临时代码段描述符及选择子TempCode        Desc    <0ffffh,TempCodeSeg,,ATCE,,>TempCode_Sel    =       TempCode-GDT                ;指向GDT的存储段描述符及选择子ToGDT           Desc    <GDTLen-1,GDTSeg,,ATDW,,>ToGDT_Sel       =       ToGDT-GDT                ;指向通用保护故障处理任务TSS的存储段描述符及选择子ToGPTSS         Desc    <GPTSSLen-1,GPTSSSeg,,ATDW,,>ToGPTSS_Sel     =       ToGPTSS-GDT                ;指向测试任务TSS的存储段描述符及选择子ToTestTSS       Desc    <TestTSSLen-1,TestTSSSeg,,ATDW,,>ToTestTSS_Sel   =       ToTestTSS-GDT                ;测试任务TSS段描述符及选择子TestTSS         Desc    <TestTSSLen-1,TestTSSSeg,,AT386TSS,,>TestTSS_Sel     =       TestTSS-GDT                ;测试任务1堆栈段描述符(DPL=1)及选择子Test1Stack      Desc    <TestStackLen-1,TestStackSeg,,ATDW+DPL1,D32,>Test1Stack_Sel  =       Test1Stack-GDT+RPL1                ;测试任务1代码段描述符(DPL=1)及选择子Test1Code       Desc    <TestCodeLen-1,TestCodeSeg,,ATCE+DPL1,D32,>Test1Code_Sel   =       Test1Code-GDT+RPL1                ;测试任务2堆栈段描述符(DPL=2)及选择子Test2Stack      Desc    <TestStackLen-1,TestStackSeg,,ATDW+DPL2,D32,>Test2Stack_Sel  =       Test2Stack-GDT+RPL2                ;测试任务2代码段描述符(DPL=2)及选择子Test2Code       Desc    <TestCodeLen-1,TestCodeSeg,,ATCE+DPL2,D32,>Test2Code_Sel   =       Test2Code-GDT+RPL2                ;测试任务3堆栈段描述符(DPL=3)及选择子Test3Stack      Desc    <TestStackLen-1,TestStackSeg,,ATDW+DPL3,D32,>Test3Stack_Sel  =       Test3Stack-GDT+RPL3                ;测试任务3代码段描述符(DPL=3)及选择子Test3Code       Desc    <TestCodeLen-1,TestCodeSeg,,ATCE+DPL3,D32,>Test3Code_Sel   =       Test3Code-GDT+RPL3                ;通用保护故障处理任务的TSS段描述符及选择子GPTSS           Desc    <GPTSSLen-1,GPTSSSeg,,AT386TSS,,>GPTSS_Sel       =       GPTSS-GDT                ;通用保护故障处理任务的堆栈段描述符及选择子GPStack         Desc    <GPStackLen-1,GPStackSeg,,ATDW,D32,>GPStack_Sel     =       GPStack-GDT                ;通用保护故障处理任务的代码段描述符及选择子GPCode          Desc    <GPCodeLen-1,GPCodeSeg,,ATCE,D32,>GPCode_Sel      =       GPCode-GDT                ;其它中断或异常处理程序代码段(一致可读)描述符及选择子ErrCode         Desc    <ErrCodeLen-1,ErrCodeSeg,,ATCCOR,D32,>ErrCode_Sel     =       ErrCode-GDT;----------------------------------------------------------------------------GDNum           =       ($-EFFGDT)/(SIZE Desc)    ;需处理基地址的描述符个数;----------------------------------------------------------------------------                ;指向测试任务的任务门TestTask        Gate    <,TestTSS_Sel,,ATTaskGate,>Test_Sel        =       TestTask-GDT;----------------------------------------------------------------------------GDTLen          =       $-GDT                     ;全局描述符表长度GDTSeg          ENDS                              ;全局描述符表段定义结束;----------------------------------------------------------------------------IDTSeg          SEGMENT PARA USE16                ;中断描述符表段(16位)IDT             LABEL   BYTE                      ;中断描述符表                REPT    13                Gate    <ErrBegin,ErrCode_Sel,,AT386TGate,>                ENDM                Gate    <,GPTSS_Sel,,ATTaskGate,> ;通用故障处理程序门描述符                REPT    242                Gate    <ErrBegin,ErrCode_Sel,,AT386TGate,>                ENDM;----------------------------------------------------------------------------IDTLen          =       $-IDT;----------------------------------------------------------------------------IDTSeg          ENDS                              ;中断描述符表段定义结束;----------------------------------------------------------------------------;其它中断或异常处理程序的代码段(一致可读);----------------------------------------------------------------------------ErrCodeSeg      SEGMENT PARA USE32                ASSUME  CS:ErrCodeSeg;----------------------------------------------------------------------------ErrMess         DB      'Error!!!'ErrMessLen      =       $-ErrMess;----------------------------------------------------------------------------ErrBegin        PROC    FAR                cld                mov     ax,ErrCode_Sel                mov     ds,ax                lea     esi,ErrMess                mov     ax,VideoBuf_Sel                mov     es,ax                mov     edi,1992                mov     ecx,ErrMessLen                mov     ah,4ehErr1:           lodsb                stosw                loop    Err1                jmp     $ErrBegin        ENDP;----------------------------------------------------------------------------ErrCodeLen      =       $ErrCodeSeg      ENDS;----------------------------------------------------------------------------GPTSSSeg        SEGMENT PARA USE16                ;通用保护故障处理任务的TSSGPTaskSS        LABEL   BYTE                DD      0                         ;任务嵌套时的链接指针                DD      0                         ;0级堆栈偏移                DW      0,0                       ;0级堆栈选择子                DD      0                         ;1级堆栈偏移                DW      0,0                       ;1级堆栈选择子                DD      0                         ;2级堆栈偏移                DW      0,0                       ;2级堆栈选择子                DD      0                         ;CR3                DW      GPBegin,0                 ;EIP                DD      0                         ;EFLAGS                DD      0                         ;EAX                DD      0                         ;ECX                DD      0                         ;EDX                DD      0                         ;EBX                DD      GPStackLen                ;ESP                DD      0                         ;EBP                DD      0                         ;ESI                DD      0                         ;EDI                DW      VideoBuf_Sel,0            ;ES                DW      GPCode_Sel,0              ;CS                DW      GPStack_Sel,0             ;SS                DW      ToTestTSS_Sel,0           ;DS                DW      ToGPTSS_Sel,0             ;FS                DW      0,0                       ;GS                DW      0,0                       ;LDTR                DW      0                         ;调试陷阱标志                DW      $+2                       ;指向I/O许可位图的偏移                DB      0ffh                      ;I/O许可位图结束标志GPTSSLen        =       $GPTSSSeg        ENDS;----------------------------------------------------------------------------GPStackSeg      SEGMENT PARA USE32                ;通用保护故障处理任务堆栈段GPStackLen      =       512                DB      GPStackLen DUP(0)GPStackSeg      ENDS;----------------------------------------------------------------------------;通用保护故障处理程序代码段;----------------------------------------------------------------------------GPCodeSeg       SEGMENT PARA USE32                ASSUME  CS:GPCodeSeg;----------------------------------------------------------------------------GPBegin         PROC    FAR                ;在屏幕左上角显示故障点                xor     edi,edi                mov     ebx,OFFSET TestTaskSS                mov     edx,DWORD PTR [ebx].TRCS                call    EchoEDX                mov     ax,(17h SHL 8)+':'                stosw                mov     edx,[ebx].TREIP                call    EchoEDX                ;演示以便看清故障点                mov     ecx,1234567h                loop    $                ;调整任务链接指针,中止故障任务                mov     ebx,OFFSET GPTaskSS                mov     ax,DemoTSS_Sel                mov     fs:[ebx].TRLink,ax                add     esp,4                iretd                jmp     GPBeginGPBegin         ENDP;----------------------------------------------------------------------------;显示edx内容的子程序;----------------------------------------------------------------------------EchoEDX         PROC                mov     ah,17h                mov     ecx,8EchoEDX1:       rol     edx,4                mov     al,dl                call    HToASCII                stosw                loop    EchoEDX1                retEchoEDX         ENDP;----------------------------------------------------------------------------;把4位二进制数转换成对应的ASCII码;----------------------------------------------------------------------------HToASCII        PROC                and     al,0fh                add     al,90h                daa                adc     al,40h                daa                retHToASCII        ENDP;----------------------------------------------------------------------------GPCodeLen       =       $GPCodeSeg       ENDS;----------------------------------------------------------------------------;测试任务的TSS段TestTSSSeg      SEGMENT PARA USE16TestTaskSS      TSS     <>                        ;TSS的固定格式部分IOMap           LABEL   BYTE                      ;I/O许可位图                DB      8 DUP(0ffh)               ;端口00h--3fh                DB      11111011b                 ;端口40h--47h                DB      3 DUP(0ffh)               ;端口48h--5fh                DB      11111101b                 ;端口60h--67h                DB      0                         ;端口68h--6fh                DB      0ffh                      ;I/O许可位图结束标志TestTSSLen      =       $TestTSSSeg      ENDS;----------------------------------------------------------------------------;测试任务的堆栈段TestStackSeg    SEGMENT PARA USE32TestStackLen    =       1024                DB      TestStackLen DUP(0)TestStackSeg    ENDS;----------------------------------------------------------------------------;测试任务的代码段TestCodeSeg     SEGMENT PARA USE32                ASSUME  CS:TestCodeSeg;----------------------------------------------------------------------------Test3Begin      PROC    FAR                cli                               ;I/O敏感指令                clts                              ;特权指令                iretd                jmp     Test3BeginTest3Begin      ENDP;----------------------------------------------------------------------------TestBegin       PROC    FAR                mov     al,0b6h                   ;使扬声器发出一长声                out     43h,al                mov     al,2                out     42h,al                mov     al,34h                out     42h,al                in      al,61h                mov     ah,al                or      al,3                out     61h,al                mov     ecx,1234567h                loop    $                mov     al,ah                out     61h,al                iretd                jmp     TestBeginTestBegin       ENDP;----------------------------------------------------------------------------TestCodeLen     =       $TestCodeSeg     ENDS;----------------------------------------------------------------------------;演示任务TSS段DemoTSSSeg      SEGMENT PARA USE16DemoTaskSS      TSS     <>                DB      0ffh                      ;I/O许可位图结束字节DemoTSSLen      =       $DemoTSSSeg      ENDS;----------------------------------------------------------------------------;演示任务的堆栈段DemoStackSeg    SEGMENT PARA USE32DemoStackLen    =       1024                DB      DemoStackLen DUP(0)DemoStackSeg    ENDS;----------------------------------------------------------------------------;演示任务的代码段DemoCodeSeg     SEGMENT PARA USE32                ASSUME  CS:DemoCodeSeg;----------------------------------------------------------------------------DemoBegin       PROC    FAR                mov     ax,ToTestTSS_Sel                mov     ds,ax                mov     ebx,OFFSET TestTaskSS                ;把测试任务1的入口点,堆栈指针和标志值(含IOPL)填入测试任务TSS                mov     WORD PTR [ebx].TRSS,Test1Stack_Sel                mov     DWORD PTR [ebx].TRESP,TestStackLen                mov     WORD PTR [ebx].TRCS,Test1Code_Sel                mov     DWORD PTR [ebx].TREIP,OFFSET TestBegin                mov     DWORD PTR [ebx].TREFLAG,IOPL1                ;通过任务门调用测试任务                CALL32  Test_Sel,0                ;把测试任务2的入口点,堆栈指针和标志值(含IOPL)填入测试任务TSS                mov     WORD PTR [ebx].TRSS,Test2Stack_Sel                mov     DWORD PTR [ebx].TRESP,TestStackLen                mov     WORD PTR [ebx].TRCS,Test2Code_Sel                mov     DWORD PTR [ebx].TREIP,OFFSET TestBegin                mov     DWORD PTR [ebx].TREFLAG,IOPL1                ;通过任务门调用测试任务                CALL32  Test_Sel,0                ;把测试任务TSS描述符内的属性置为"可用"                mov     ax,ToGDT_Sel                mov     fs,ax                mov     fs:TestTSS.Attributes,AT386TSS                ;把测试任务3的入口点,堆栈指针和标志值(含IOPL)填入测试任务TSS                mov     WORD PTR [ebx].TRSS,Test3Stack_Sel                mov     DWORD PTR [ebx].TRESP,TestStackLen                mov     WORD PTR [ebx].TRCS,Test3Code_Sel                mov     DWORD PTR [ebx].TREIP,OFFSET Test3Begin                mov     DWORD PTR [ebx].TREFLAG,IOPL2                ;通过任务门调用测试任务                CALL32  Test_Sel,0                ;把测试任务TSS描述符内的属性置为"可用"                mov     ax,ToGDT_Sel                mov     fs,ax                mov     fs:TestTSS.Attributes,AT386TSS                ;把测试任务4的入口点,堆栈指针和标志值(含IOPL)填入测试任务TSS                mov     WORD PTR [ebx].TRSS,Test3Stack_Sel                mov     DWORD PTR [ebx].TRESP,TestStackLen                mov     WORD PTR [ebx].TRCS,Test3Code_Sel                mov     DWORD PTR [ebx].TREIP,OFFSET Test3Begin                mov     DWORD PTR [ebx].TREFLAG,IOPL3                ;通过任务门调用测试任务                CALL32  Test_Sel,0                JUMP32  TempCode_Sel,<OFFSET ToDOS>DemoBegin       ENDP;----------------------------------------------------------------------------DemoCodeLen     =       $DemoCodeSeg     ENDS;----------------------------------------------------------------------------TempCodeSeg     SEGMENT PARA USE16                ;演示任务的临时代码段                ASSUME  CS:TempCodeSeg;----------------------------------------------------------------------------Virtual         PROC    FAR                ;置数据段寄存器为空                mov     ax,0                mov     ds,ax                mov     es,ax                mov     fs,ax                mov     gs,ax                ;置堆栈指针                mov     ax,DemoStack_Sel                mov     ss,ax                mov     esp,DemoStackLen                ;置任务寄存器                mov     ax,DemoTSS_Sel                ltr     ax                ;转演示代码段                JUMP16  DemoCode_Sel,DemoBeginToDOS:          clts                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      ?                         ;用于保存实方式下的SSRDataSeg        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                lgdt    QWORD PTR VGDTR           ;装载GDTR                mov     SSVar,ss                  ;保存堆栈指针                mov     SPVar,sp                sidt    QWORD PTR NORVIDTR        ;保存IDTR                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                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     Start

3.关于实例九的说明

    为了节省篇幅,同时也反映任务状态段的作用,实例通过任务门调用的四个测试任务合用一个任务状态段。从源程序可见,这种合用,实际上是串行的。先把测试任务1的入口点填入测试任务状态段,同时填入堆栈指针,然后调用测试任务1。在测试任务1完成后,再填入测试任务2的入口点,也填入堆栈指针,然后调用测试任务2。依次类推。
    通用保护故障处理程序作为一个独立的任务出现。再发生通用保护故障后,通用保护故障处理程序在屏幕上显示故障点的选择子和偏移,然后通过调整存放在任务状态段内的任务连接指针的方法,中止引起故障的测试任务。

 
 

上一篇:伪操作  下一篇:SHELL&nbsp;排序测试