;演示在任务内如何进行特权级变换

;程序名
;演示在任务内如何进行特权级变换
;
INCLUDE 386CD.ASM  ;参见实例3
;
.386p
;------------------------------------
;全局描述符表GDT
GDTSEGSEGMENT PARA USE16
GDT LABEL BYTE
DUMMY DESCRIPTOR <>
NORMAL DESCRIPTOR <0FFFFH,0,0,ATDW,0>
NORMAL_SEL = NORMAL - GDT
EFFGDT LABEL BYTE
;演示任务状态段TSS描述符
DEMOTSS DESCRIPTOR <DemoTSSLEN-1,DemoTSSSEG,,AT386TSS,>
DemoTSS_SEL = DEMOTSS - GDT
;演示任务LDT段描述符
DEMOLDTD DESCRIPTOR <DemoLDTLEN-1,DemoLDTSEG,,ATLDT,>
DemoLDT_SEL = DEMOLDTD - GDT
;临时代码段描述符
TEMPCODE DESCRIPTOR <0FFFFH,TempCodeSEG,,ATCE,>
TempCode_SEL = TEMPCODE - GDT
;视频缓冲区段描述符(DPL=3)
VIDEOBUFF DESCRIPTOR <0FFFFH,,,0F00H+ATDW+DPL3,0>
Video_SEL = VIDEOBUFF - GDT
GDNUM = ($- EFFGDT)/(SIZE DESCRIPTOR)
GDTLEN = $ - GDT
GDTSEG ENDS
;------------------------------------------------------
;演示任务局部描述符表LDT
DemoLDTSEG SEGMENT PARA USE16
DEMOLDT LABEL BYTE
;0级堆栈段描述符(32位段)
DEMOSTACK0 DESCRIPTOR <DemoStack0LEN-1,DemoStack0SEG,,ATDW+D32,>
DemoStack0_SEL = (DemoStack0 - DEMOLDT) + TIL
;1级堆栈段描述符(DPL=1)
DEMOSTACK1 DESCRIPTOR <DemoStack1LEN-1,DemoStack1SEG,,ATDW + D32+DPL1,>
DemoStack1_SEL = (DemoStack1 - DEMOLDT)+TIL+RPL1
;3级堆栈段描述符(DPL=3)
DEMOSTACK3 DESCRIPTOR <DemoStack3LEN-1,DemoStack3SEG,,ATDW + DPL3,>
DemoStack3_SEL = (DemoStack3 - DEMOLDT)+ TIL + RPL3
;演示代码段描述符(32位段,DPL=3)
DEMOCODE DESCRIPTOR <DemoCodeLEN-1,DemoCodeSEG,,ATCE+D32+DPL3,>
DemoCode_SEL = (DEMOCODE - DEMOLDT)+ TIL +RPL3
;过渡代码段描述符(32位段)
T32CODE DESCRIPTOR <T32CodeLEN-1,T32CodeSEG,,ATCE+D32,>
T32Code_SEL = (T32CODE-DEMOLDT)+TIL
;显示子程序代码段描述符(32位段,DPL =1 )
ECHOSUBR DESCRIPTOR <EchoSUBRLEN-1,EchoSUBRSEG,,ATCER+D32+DPL1,>
Echo_SEL1 = (ECHOSUBR - DEMOLDT)+TIL+RPL1
Echo_SEL3 = (ECHOSUBR - DEMOLDT)+TIL+RPL3
DemoLDNUM = ($-DEMOLDT)/(SIZE DESCRIPTOR)
;指向过渡代码段内T32Begin点的调用门(DPL=0)
TOT32GATEA GATE <T32Begin,T32Code_SEL,0,AT386CGAT,0>
ToT32A_SEL = (TOT32GATEA - DemoLDT)+TIL
;指向过渡代码段内T32End点的调用门(DPL=3)
TOT32GATEB GATE <T32End,T32Code_SEL,0,AT386CGAT+DPL3,0>
ToT32B_SEL = (TOT32GATEB -DEMOLDT)+TIL
;指向显示子程序的调用门(DPL=3)
TOECHOGATE GATE <EchoSUB,Echo_SEL3,0,AT386CGAT+DPL3,0>
ToEcho_SEL = (TOECHOGATE - DemoLDT)+TIL
DemoLDTLEN = $ - DemoLDT
DemoLDTSEG ENDS
;------------------------------------------------------------
;演示任务的TSS段
DemoTSSSEG SEGMENT PARA USE16
        DD  0                ;BACK
        DW  DemoStack0LEN,0  ;0级堆栈指针
        DW  DemoStack0_SEL,0 ;初始化
        DW  DemoStack1LEN,0  ;1级堆栈指针
        DW  DemoStack1_SEL,0 ;初始化
        DD  ?                ;2级堆栈指针
        DW  ?,0              ;未初始化
        DD  0                ;CR3
        DD  ?                ;EIP
        DD  ?                ;EFLAGS
        DD  ?                ;EAX
        DD  ?                ;ECX
        DD  ?                ;EDX
        DD  ?                ;EBX
        DD  ?                ;ESP
        DD  ?                ;EBP
        DD  ?                ;ESI
        DD  ?                ;EDI
        DW  ?,0              ;ES
        DW  ?,0              ;CS
        DW  ?,0              ;SS
        DW  ?,0              ;DS
        DW  ?,0              ;FS
        DW  ?,0              ;GS
        DW  DemoLDT_SEL,0    ;LDT
        DW  0
        DW  $+2              ;指向I/O许可位图
        DB  0FFH             ;I/O许可位图结束标志
    DemoTSSLEN=$
 DemoTSSEG ENDS
 ;----------------------------------------------
 ;演示任务0级堆栈段(32位段)
 DemoStack0SEG SEGMENT PARA USE32
 DemoStack0LEN = 512
          DB  DemoStck0LEN DUP (0)
 DemoStack0SEG ENDS
 ;--------------------------------------------------
 ;演示任务1级堆栈段(16位段)
 DemoStack1SEG SEGMENT PARA USE32
 DemoStack1LEN =512
         DB DemoStack1LEN DUP (0)
 DemoStack1SEG ENDS
 ;----------------------------------------------------
 ;演示任务3级堆栈段(16位段)
 DemoStack3SEG SEGMENT PARA USE16
 DemoStack3LEN = 512
          DB DemoStack3LEN  DUP (0)
 DemoStack3SEG ENDS
 ;------------------------------------------------------
 ;演示任务显示子程序代码段(32位段,1级)
 EchoSUBRSEG SEGMENT PARA USE32
 MESSAGE DB 'CPL=',0
 ASSUME CS:EchoSUBRSEG
  ;显示调用程序的执行特权级
  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                           ;视频缓冲区段基地址00000000H
      MOV EDI,0B8000H                     ;视频缓冲区段B8000H开始
      MOV ESI,OFFSET MESSAGE
      MOV AH,17H                          ;置显示属性
  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,17H
      STOSW                               ;显示之
      POP EBP
      RETF                                ;返回
 EchoSUB ENDP
 EchoSUBRLEN = $                      
 EchoSUBRSEG ENDS
 ;----------------------------------------------------------
 ;演示任务的演示代码段(32位段,3级)
 DemoCodeSEG SEGMENT PARA USE32
 ASSUME CS:DemoCodeSEG
 DemoBegin:
  ;显示当前特权级(变换到1级)
  CALL32 ToEcho_SEL,0
  ;转到过渡代码段(变换到0级)
  CALL32 ToT32B_SEL,0
  DemoCodeLEN = $
  DemoCodeSEG ENDS
  ;--------------------------------------------------------
  演示任务的过渡代码段(32位段,0级)
  T32CODESEG SEGMENT PARA USE32
  ASSUME CS:T32CODESEG
  T32Begin:
         ;建立0级堆栈
         MOV AX,DemoStack0_SEL
         MOV SS,AX
         MOV ESP,DemoStack0LEN
         ;压入3级堆栈指针
         PUSH DWORD PTR DemoStack3_SEL
         PUSH DWORD PTR DemoStack3LEN
         ;压入入口点
         PUSH DWORD PTR DemoCode_SEL
         PUSH OFFSET DemoBegin
         ;利用RET实现转3级的演示代码段
         RETF
 T32End:;转临时代码段
         JUMP32  TempCode_SEL,<OFFSET ToReal>
 T32CodeLEN = $
 T32CODESEG ENDS
 ;-----------------------------------------------
 ;临时代码段(16位段,0级)
 TempCodeSEG SEGMENT PARA USE16
     ASSUME CS:TempCodeSEG
  Virtual:;装载TR
    MOV AX,DemoTSS_SEL
    LTR AX
    ;装载LDTR
    MOV BX,DemoLDT_SEL
    LLDT BX
    ;通过调用门转过渡段
    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 EAX,0FFFEH
    MOV CR0,EAX                       ;返回实方式
    JUMP16 <SEG REAL>,<OFFSET REAL>
    TempCodeLEN = $
    TempCodeSEG ENDS
    ;===========================================
    ;实方式下的数据段
    RDataSEG SEGMENT PARA USE16
    VGDTR PDESC <GDTLEN-1,>
    SPVAR DW ?
    SSVAR DW ?
    RDataSEG ENDS
    ;--------------------------------------------------
    ;实方式下的代码段
    RCodeSEG SEGMENT PARA USE16
    ASSUME CS:RCodeSEG,DS:RDataSEG
    Start:
         MOV AX,RDataSEG
         MOV DS,AX
         CLD
         CALL INIT_GDT    ;初始化GDT
         ;
         MOV AX,DemoLDTSEG
         MOV FS,AX
         MOV SI,OFFSET DemoLDT
         CALL INIT_LDT     ;初始化LDT
         ;
         MOV SSVAR,SS
         MOV SPVAR,SP
         ;装载GDTR和切换到保护方式
         LGDT QWORD PTR VGDTR
         CLI
         MOV EAX,CR0
         OR  AX,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
  ;-----------------------------------------
  ;初始化全局描述符表的子程序
  ;(1)把定义时预置的段值转换成32位段基地址并置入描述符内相应字段
  ;(2)初始化为GDTR准备的伪描述符
  INIT_GDT PROC NEAR
     PUSH DS
     MOV AX,GDTSEG
     MOV DS,AX
     MOV CX,GDNUM     ;GDNUM 是初始化的描述符个数
     MOV SI,OFFSET EFFGDT ;EFFGDT是开始偏移
 INITG:MOV AX,[SI].BASEL  ;取出预置的段值
       MOVZX EAX,AX       ;扩展到32位
       SHL EAX,4
       SHLD EDX,EAX,16    ;分解到2个16位寄存器
       MOV [SI].BASEL,AX
       MOV [SI].BASEM,DL  ;置入描述符相应字段
       MOV [SI].BASEH,DH
       ADD SI,SIZE DESCRIPTOR ;调整到下一描述符
       LOOP INITG
       POP DS
       ;
       MOV BX,16   ;初始化为GDTR准备的伪描述符
       MOV AX,GDTSEG
       MUL BX
       MOV WORD PTR VGDTR.BASE,AX
       MOV WORD PTR VGDTR.BASE+2,DX
       RET
       INIT_GDT ENDP
       ;
       ;初始化演示任务局部描述符表的子程序
       ;把定义时预置的段值转换成32位段基地址并置入描述符内相应字段
       ;入口参数:FS:SI=第一个要初始化的描述符
       ;CX=要初始化的描述符个数
       INIT_LDT PROC
       ILDT:MOV AX,FS:[SI].BASEL
            MOVZX,EAX,AX
            SHL EAX,4
            SHLD EDX,EAX,16
            MOV FS:[SI].BASEL,AX
            MOV FS:[SI].BASEM,DL
            MOV FS:[SI].BASEH,DH
            ADD SI,SIZE DESCRIPTOR
            LOOP ILDT
            RET
            INIT_LDT ENDP
            RCodeSEG ENDS
            END Start
      
      
      
      
      
      
        
        
   
   
   
   
 
 
        
        
        
   
     
     
    
       

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值