WEB开发网
开发学院软件开发汇编语言 汇编教程:控制转移(2) 阅读

汇编教程:控制转移(2)

 2009-02-16 09:36:49 来源:WEB开发网   
核心提示:(9)实模式下的数据和代码段,该实例的逻辑功能是显示演示代码段执行时的当前特权级CPL,汇编教程:控制转移(2)(4),源程序清单如下:;名称:ASM4.ASM;功能:演示任务内有特权级变换的转移;编译:TASM ASM4.ASM;连接:TLINK /32 ASM4.OBJ;INCLUDE 386SCD.INC;GDT

(9)实模式下的数据和代码段。

该实例的逻辑功能是显示演示代码段执行时的当前特权级CPL。源程序清单如下:

;名称:ASM4.ASM
;功能:演示任务内有特权级变换的转移
;编译:TASM ASM4.ASM
;连接:TLINK /32 ASM4.OBJ
;----------------------------------------------------------------------------
INCLUDE     386SCD.INC
;----------------------------------------------------------------------------
GDTSeg     SEGMENT PARA USE16        ;全局描述符表数据段(16位)
;----------------------------------------------------------------------------
        ;全局描述符表
GDT       LABEL  BYTE
        ;空描述符
DUMMY      Desc  <>
        ;规范段描述符
Normal     Desc  <0ffffh,,,ATDW,,>
        ;视频缓冲区段描述符(DPL=3)
VideoBuf    Desc  <07fffh,8000h,0bh,ATDW+DPL3,,>
;----------------------------------------------------------------------------
EFFGDT     LABEL  BYTE
        ;任务状态段TSS描述符
DemoTSS     Desc  <DemoTssLen-1,DemoTSSSeg,,AT386TSS,,>
        ;局部描述符表段的描述符
DemoLDTD    Desc  <DemoLDTLen-1,DemoLDTSeg,,ATLDT,,>
        ;临时代码段描述符
TempCode    Desc  <0ffffh,TempCodeSeg,,ATCE,,>
;----------------------------------------------------------------------------
GDTLen     =    $-GDT           ;全局描述符表长度
GDNum      =    ($-EFFGDT)/(SIZE Desc)  ;需特殊处理的描述符数
;----------------------------------------------------------------------------
Normal_Sel   =    Normal-GDT        ;规范段描述符选择子
Video_Sel    =    VideoBuf-GDT       ;视频缓冲区段描述符选择子
;----------------------------------------------------------------------------
DemoTSS_Sel   =    DemoTSS-GDT        ;任务状态段描述符选择子
DemoLDT_Sel   =    DemoLDTD-GDT       ;局部描述符表段的选择子
TempCode_Sel  =    TempCode-GDT       ;临时代码段的选择子
;----------------------------------------------------------------------------
GDTSeg     ENDS               ;全局描述符表段定义结束
;----------------------------------------------------------------------------
DemoLDTSeg   SEGMENT PARA USE16        ;局部描述符表数据段(16位)
;----------------------------------------------------------------------------
DemoLDT     LABEL  BYTE           ;局部描述符表
        ;0级堆栈段描述符(32位段)
DemoStack0   Desc  <DemoStack0Len-1,DemoStack0Seg,,ATDW+DPL0,D32,>
        ;1级堆栈段描述符(32位段)
DemoStack1   Desc  <DemoStack1Len-1,DemoStack1Seg,,ATDW+DPL1,D32,>
        ;3级堆栈段描述符(16位段)
DemoStack3   Desc  <DemoStack3Len-1,DemoStack3Seg,,ATDW+DPL3,,>
        ;代码段描述符(32位段,DPL=3)
DemoCode    Desc  <DemoCodeLen-1,DemoCodeSeg,,ATCE+DPL3,D32,>
        ;过渡代码段描述符(32位段)
T32Code     Desc  <T32CodeLen-1,T32CodeSeg,,ATCE,D32,>
        ;显示子程序代码段描述符(32位段,DPL=1)
EchoSubR    Desc  <EchoSubRLen-1,EchoSubRSeg,,ATCER+DPL1,D32,>
;----------------------------------------------------------------------------
DemoLDNum    =    ($-DemoLDT)/(SIZE Desc)
;----------------------------------------------------------------------------
        ;0级堆栈描述符选择子(RPL=0)
DemoStack0_Sel =    DemoStack0-DemoLDT+TIL+RPL0
        ;1级堆栈描述符选择子(RPL=1)
DemoStack1_Sel =    DemoStack1-DemoLDT+TIL+RPL1
        ;3级堆栈描述符选择子(RPL=3)
DemoStack3_Sel =    DemoStack3-DemoLDT+TIL+RPL3
        ;代码段描述符选择子(RPL=3)
DemoCode_Sel  =    DemoCode-DemoLDT+TIL+RPL3
        ;过渡代码段描述符选择子
T32Code_Sel   =    T32Code-DemoLDT+TIL
        ;显示子程序代码段描述符选择子(RPL=1)
Echo_Sel1    =    EchoSubR-DemoLDT+TIL+RPL1
        ;显示子程序代码段描述符选择子(RPL=3)
Echo_Sel3    =    EchoSubR-DemoLDT+TIL+RPL3
;----------------------------------------------------------------------------
        ;指向过渡代码段内T32Begin点的调用门(DPL=0)
ToT32GateA   Gate  <T32Begin,T32Code_Sel,,AT386CGate,>
        ;指向过渡代码段内T32End点的调用门(DPL=3)
ToT32GateB   Gate  <T32End,T32Code_Sel,,AT386CGate+DPL3,>
        ;指向显示子程序代码段的调用门(DPL=3)
ToEchoGate   Gate  <EchoSub,Echo_Sel3,,AT386CGate+DPL3,>
;----------------------------------------------------------------------------
DemoLDTLen   =    $-DemoLDT
;----------------------------------------------------------------------------
        ;指向过渡代码段内T32Begin点的调用门的选择子
ToT32A_Sel   =    ToT32GateA-DemoLDT+TIL
        ;指向过渡代码段内T32End点的调用门的选择子
ToT32B_Sel   =    ToT32GateB-DemoLDT+TIL
        ;显示子程序调用门的选择子
ToEcho_Sel   =    ToEchoGate-DemoLDT+TIL
;----------------------------------------------------------------------------
DemoLDTSeg   ENDS               ;局部描述符表段定义结束
;----------------------------------------------------------------------------
DemoTSSSeg   SEGMENT PARA USE16        ;任务状态段TSS
;----------------------------------------------------------------------------
        DD   0             ;Back
        DD   DemoStack0Len       ;0级堆栈指针
        DD   DemoStack0_Sel      ;初始化
        DD   DemoStack1Len       ;1级堆栈指针
        DD   DemoStack1_Sel      ;初始化
        DD   0             ;2级堆栈指针
        DD   0             ;未初始化
        DD   0             ;CR3
        DD   0             ;EIP
        DD   0             ;EFLAGS
        DD   0             ;EAX
        DD   0             ;ECX
        DD   0             ;EDX
        DD   0             ;EBX
        DD   0             ;ESP
        DD   0             ;EBP
        DD   0             ;ESI
        DD   0             ;EDI
        DD   0             ;ES
        DD   0             ;CS
        DD   0             ;SS
        DD   0             ;DS
        DD   0             ;FS
        DD   0             ;GS
        DD   DemoLDT_Sel        ;LDT
        DW   0             ;调试陷阱标志
        DW   $+2            ;指向I/O许可位图
        DW   0ffffh          ;I/O许可位图结束标志
;----------------------------------------------------------------------------
DemoTSSLen   =    $
;----------------------------------------------------------------------------
DemoTSSSeg   ENDS               ;任务状态段TSS结束
;----------------------------------------------------------------------------
DemoStack0Seg  SEGMENT DWORD STACK USE32     ;0级堆栈段(32位段)
DemoStack0Len  =    512
        DB   DemoStack0Len DUP(?)
DemoStack0Seg  ENDS               ;0级堆栈段结束
;----------------------------------------------------------------------------
DemoStack1Seg  SEGMENT DWORD STACK USE32     ;1级堆栈段(32位段)
DemoStack1Len  =    512
        DB   DemoStack1Len DUP(?)
DemoStack1Seg  ENDS               ;1级堆栈段结束
;----------------------------------------------------------------------------
DemoStack3Seg  SEGMENT DWORD STACK USE16     ;3级堆栈段(16位段)
DemoStack3Len  =    512
        DB   DemoStack3Len DUP(?)
DemoStack3Seg  ENDS               ;3级堆栈段结束
;----------------------------------------------------------------------------
EchoSubRSeg   SEGMENT PARA USE32        ;显示子程序代码段(32位,1级)
        ASSUME CS:EchoSubRSeg
;----------------------------------------------------------------------------
Message     DB   'CPL=',0         ;显示信息(该代码段可读)
;----------------------------------------------------------------------------
EchoSub     PROC  FAR
        cld
        push  ebp
        mov   ebp,esp
        mov   ax,Echo_Sel1       ;该代码段是可读段
        mov   ds,ax           ;采用RPL=1的选择子
        mov   ax,Video_Sel
        mov   es,ax
        mov   edi,1996
        mov   esi,OFFSET Message
        mov   ah,4eh          ;置显示属性(红底黄字)
EchoSub1:    lodsb
        or   al,al
        jz   EchoSub2
        stosw
        jmp   EchoSub1
EchoSub2:    mov   eax,[ebp+8]        ;从堆栈中取调用程序的选择子
        and   al,3           ;调用程序的CPL在CS的RPL字段
        add   al,'0'
        mov   ah,4eh          ;置显示属性(红底黄字)
        stosw
        pop   ebp
        retf
EchoSub     ENDP
;----------------------------------------------------------------------------
EchoSubRLen   =    $
;----------------------------------------------------------------------------
EchoSubRSeg   ENDS               ;显示子程序代码段结束
;----------------------------------------------------------------------------
DemoCodeSeg   SEGMENT PARA USE32        ;32位代码段(3级)
        ASSUME CS:DemoCodeSeg
;----------------------------------------------------------------------------
DemoBegin    PROC  FAR
        CALL32 ToEcho_Sel,0       ;显示当前特权级(变换到1级)
        CALL32 ToT32B_Sel,0       ;转到过渡代码段(变换到0级)
DemoBegin    ENDP
DemoCodeLen   =    $
;----------------------------------------------------------------------------
DemoCodeSeg   ENDS               ;32位代码段结束
;----------------------------------------------------------------------------
T32CodeSeg   SEGMENT PARA USE32        ;32位过渡代码段(0级)
        ASSUME CS:T32CodeSeg
;----------------------------------------------------------------------------
T32Begin    PROC  FAR
        mov   ax,DemoStack0_Sel     ;建立0级堆栈
        mov   ss,ax
        mov   esp,DemoStack0Len
        push  DWORD PTR DemoStack3_Sel ;压入3级堆栈指针
        push  DemoStack3Len
        push  DWORD PTR DemoCode_SEL  ;压入入口点
        push  OFFSET DemoBegin
        retf               ;利用RET实现转3级的演示代码
T32Begin    ENDP
;----------------------------------------------------------------------------
T32End     PROC  FAR
        JUMP32 TempCode_Sel,<OFFSET ToReal>
T32End     ENDP
T32CodeLen   =    $
;----------------------------------------------------------------------------
T32CodeSeg   ENDS
;----------------------------------------------------------------------------
TempCodeSeg   SEGMENT PARA USE16        ;16位临时代码段(0级)
        ASSUME CS:TempCodeSeg
;----------------------------------------------------------------------------
Virtual     PROC  FAR
        mov   ax,DemoTSS_Sel      ;装载TR
        ltr   ax
        mov   ax,DemoLDT_Sel      ;装载LDTR
        lldt  ax
        JUMP16 ToT32A_Sel,0       ;通过调用门转过渡段
ToReal:     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
TempCodeLen   =    $
;----------------------------------------------------------------------------
TempCodeSeg   ENDS
;============================================================================
RDataSeg    SEGMENT PARA USE16        ;实方式数据段
VGDTR      PDesc  <GDTLen-1,>        ;GDT伪描述符
SPVar      DW   ?             ;用于保存实方式下的SP
SSVar      DW   ?             ;用于保存实方式下的SS
RDataSeg    ENDS
;----------------------------------------------------------------------------
RCodeSeg    SEGMENT PARA USE16
        ASSUME CS:RCodeSeg,DS:RDataSeg
;----------------------------------------------------------------------------
Start      PROC
        mov   ax,RDataSeg
        mov   ds,ax
        cld
        CALL  InitGDT          ;初始化全局描述符表GDT
        mov   ax,DemoLDTSeg
        mov   fs,ax
        mov   si,OFFSET DemoLDT
        mov   cx,DemoLDNum
        CALL  InitLDT          ;初始化局部描述符表LDT
        mov   SSVar,ss
        mov   SPVar,sp
        lgdt  QWORD PTR VGDTR      ;装载GDTR并切换到保护方式
        cli
        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    ;又回到实方式
        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
;----------------------------------------------------------------------------
;入口参数:FS:SI=第一个要初始化的描述符,CX=要初始化的描述符数
;----------------------------------------------------------------------------
InitLDT     PROC
ILDT:      mov   ax,WORD PTR FS:[si].BaseL
        movzx  eax,ax
        shl   eax,4
        shld  edx,eax,16
        mov   WORD PTR fs:[si].BaseL,ax
        mov   BYTE PTR fs:[si].BaseM,dl
        mov   BYTE PTR fs:[si].BaseH,dh
        add   si,SIZE Desc
        loop  ILDT
        ret
InitLDT     ENDP
;----------------------------------------------------------------------------
RCodeSeg    ENDS
        END   Start

上一页  1 2 3 4 

Tags:汇编 教程 控制

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接