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

汇编教程:控制转移

 2008-12-27 09:34:56 来源:WEB开发网   
核心提示:4.装载数据段和堆栈段寄存器时的特权检测上面简单地说明了把选择子装入代码段寄存器CS时为实现保护而进行的检测,下面也简单地说明在把选择子装入数据段寄存器和堆栈段寄存器时要进行的检测,汇编教程:控制转移(2), 在把选择子装入数据段寄存器DS、ES、FS或GS时,要进行如下检测: (1)选择子不能为空; (2)选择子指定
4.装载数据段和堆栈段寄存器时的特权检测

上面简单地说明了把选择子装入代码段寄存器CS时为实现保护而进行的检测,下面也简单地说明在把选择子装入数据段寄存器和堆栈段寄存器时要进行的检测。

在把选择子装入数据段寄存器DS、ES、FS或GS时,要进行如下检测:

(1)选择子不能为空;

(2)选择子指定的描述符必须是数据段描述符、可读可执行的代码段或一致可读的可执行代码段的描述符;

(3)对于数据段和可读可执行代码段,要求CPL<=DPL,RPL<=DPL;

(4)对应的段必须存在。

若装入的选择子不满足上述要求,则会产生异常。

在把选择子装入堆栈段寄存器SS时要进行如下检测:

(1)选择子不能为空;

(2)选择子指定的描述符必须是可读写的数据段描述符;

(3)要求CPL=DPL=RPL;

(4)对应段必须存在。

若装入的选择子不满足上述条件,则在装入SS时就会引起异常。

<二>演示任务内无特权级变换转移的实例(实例三)

在实例二中,32位代码段到16位代码段的转移就是任务内无特权级转移的例子。

下面再给出一个用于演示任务内无特权级变换转移的实例。该实例使用了段间转移指令JMP、段间调用指令CALL和段间返回指令RET实现同一任务内相同特权级的转移。该实例还建立并使用了局部描述符表LDT。

1.实现步骤和源程序

实现步骤如下:(1)实模式下的初始化,包括对GDT和演示任务LDT的初始化,装载GDTR;(2)从实模式切换到保护模式,处于0特权级;(3)装载LDTR,并设置堆栈;(4)利用段间转移指令JMP实现从代码段K到同级代码段L的转移;(5)利用段间调用指令CALL调用同级代码段C中的子程序D显示字符串信息;(6)利用段间调用指令CALL调用同级代码段C中的子程序H把十六进制数转换成对应的ASCII码;(7)再利用段间调用指令CALL调用同级代码段C中的子程序D显示字符串信息;(8)利用段间转移指令JMP实现从代码段L到代码段K的转移;(9)从保护模式切换到实模式;(10)在实模式下结束程序。

  该实例的逻辑功能是用十六进制数的形式显示代码段L的段界限的值。源程序如下:

;名称:ASM3.ASM
;功能:演示任务内无特权级变换的转移
;编译:TASM ASM3.ASM
;连接:TLINK ASM3.OBJ
;----------------------------------------------------------------------------
INCLUDE     386SCD.INC
;----------------------------------------------------------------------------
GDTSeg     SEGMENT PARA USE16 'GDT'     ;全局描述符表数据段(16位)
;----------------------------------------------------------------------------
GDT       LABEL  BYTE           ;全局描述符表
DUMMY      Desc  <>            ;空描述符
Normal     Desc  <0ffffh,,,ATDW,,>     ;规范段描述符
CodeK      Desc  <0ffffh,,,ATCE,,>     ;代码段K的描述符
LDTable     Desc  <LDTLen-1,,,ATLDT,,>   ;局部描述符表段的描述符
;----------------------------------------------------------------------------
GDTLen     =    $-GDT           ;全局描述符表长度
;----------------------------------------------------------------------------
Normal_Sel   =    Normal-GDT        ;规范段描述符选择子
CodeK_Sel    =    CodeK-GDT         ;代码段K的选择子
LDT_Sel     =    LDTable-GDT        ;局部描述符表段的选择子
;----------------------------------------------------------------------------
GDTSeg     ENDS               ;全局描述符表段定义结束
;----------------------------------------------------------------------------
LDTSeg     SEGMENT PARA USE16 'LDT'     ;局部描述符表数据段(16位)
LDT       LABEL  BYTE           ;局部描述符表
;代码段L的描述符
CodeL      Desc  <CodeLLen-1,CodeLSeg,,ATCE,,>
;代码段C的描述符
CodeC      Desc  <CodeCLen-1,CodeCSeg,,ATCE,,>
;显示缓冲区段描述符
VideoBuf    Desc  <0ffffh,0b800h,,ATDW,,>
;LDT别名段描述符(DPL=3)
ToLDT      Desc  <LDTLen-1,LDTSEG,,ATDR+DPL3,,>
;显示信息缓冲区数据段描述符(DPL=3)
MData      Desc  <MDataLen-1,MDataSeg,,ATDW+DPL3,,>
;堆栈段描述符
StackS     Desc  <TopOfS-1,StackSeg,,ATDWA,,>
;----------------------------------------------------------------------------
LDTLen     =    $-LDT           ;LDT所占字节数
LDNum      =    ($-LDT)/(SIZE Desc)    ;LDT含描述符项数
;----------------------------------------------------------------------------
CodeL_Sel    =    CodeL-LDT+TIL       ;代码段L的选择子
CodeC_Sel    =    CodeC-LDT+TIL       ;代码段C的选择子
Video_Sel    =    VideoBuf-LDT+TIL     ;显示缓冲区选择子
ToLDT_Sel    =    ToLDT-LDT+TIL       ;LDT别名段选择子
MData_Sel    =    MData-LDT+TIL+RPL3    ;显示信息数据段选择子
Stack_Sel    =    StackS-LDT+TIL      ;堆栈段选择子
;----------------------------------------------------------------------------
LDTSeg     ENDS               ;局部描述符表段定义结束
;----------------------------------------------------------------------------
MDataSeg    SEGMENT PARA USE16 'MDATA'    ;显示信息缓冲区数据段
;----------------------------------------------------------------------------
Message     DB   'Value=',0
Buffer     DB   80 DUP(0)
MDataLen    =    $
;----------------------------------------------------------------------------
MDataSeg    ENDS               ;显示缓冲区数据段结束
;----------------------------------------------------------------------------
StackSeg    SEGMENT DWORD USE16 'STACK'    ;堆栈段
;----------------------------------------------------------------------------
         DW   512 DUP(?)
TopOfS     =    $
;----------------------------------------------------------------------------
StackSeg    ENDS               ;堆栈段结束
;----------------------------------------------------------------------------
CodeCSeg    SEGMENT PARA USE16 'CODEC'    ;任务代码段C
         ASSUME CS:CodeCSeg
;----------------------------------------------------------------------------
;显示信息子程序
;入口参数:fs:si指向要显示的以0结尾的字符串,es:di指向显示缓冲区
;----------------------------------------------------------------------------
DispMsg     PROC  FAR
         mov   ah,01001110b
Disp1:     mov   al,BYTE PTR fs:[si]
         inc   si
         or   al,al
         jz   Disp2
         mov   WORD PTR es:[di],ax
         inc   di
         inc   di
         jmp   Disp1
Disp2:     ret
DispMsg     ENDP
;----------------------------------------------------------------------------
;把AL寄存器低4位二进制数(一位16进制数)转换成ASCII码
;----------------------------------------------------------------------------
HToASCII    PROC  FAR
         and   al,00001111b
         add   al,90h
         daa
         adc   al,40h
         daa
         ret
HToASCII    ENDP
;----------------------------------------------------------------------------
CodeCLen    =    $
;----------------------------------------------------------------------------
CodeCSeg    ENDS               ;代码段C定义结束
;----------------------------------------------------------------------------
CodeLSeg    SEGMENT PARA USE16 'CODEL'
         ASSUME CS:CodeLSeg
;----------------------------------------------------------------------------
Virtual2    PROC  FAR
         mov   ax,Video_Sel       ;设置显示缓冲区指针
         mov   es,ax
         mov   di,1986
         mov   ax,MData_Sel       ;设置提示信息缓冲区指针
         mov   fs,ax
         mov   si,OFFSET Message
         CALL16 CodeC_Sel,DispMsg     ;显示提示信息
         mov   ax,ToLDT_Sel       ;把演示任务的LDT的别名
         mov   gs,ax           ;段的描述符选择子装入GS
         mov   dx,WORD PTR gs:CodeL.LimitL
         mov   si,OFFSET Buffer     ;取代码段L的段界限值
         mov   cx,4           ;并转成对应可显示字符串
Vir:      rol   dx,4
         mov   al,dl
         CALL16 CodeC_Sel,HToASCII
         mov   BYTE PTR fs:[si],al
         inc   si
         loop  Vir
         mov   WORD PTR fs:[si],'H'
         mov   si,OFFSET Buffer
         CALL16 CodeC_Sel,DispMsg
         JUMP16 CodeK_Sel,Virtual3
CodeLLen    =    $
Virtual2    ENDP
;----------------------------------------------------------------------------
CodeLSeg    ENDS
;----------------------------------------------------------------------------
CodeKSeg    SEGMENT PARA USE16 'CODEK'
         ASSUME CS:CodeKSeg
;----------------------------------------------------------------------------
Virtual1    PROC  FAR
         mov   ax,LDT_Sel
         LLDT  ax            ;加载局部描述符表寄存器LDTR
         mov   ax,Stack_Sel
         mov   ss,ax           ;建立演示任务堆栈
         mov   sp,OFFSET TopOfS
         JUMP16 CodeL_Sel,Virtual2
Virtual3:    mov   ax,Normal_Sel
         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>
CodeKLen    =    $
Virtual1    ENDP
;----------------------------------------------------------------------------
CodeKSeg    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
;----------------------------------------------------------------------------
Start      PROC
         ASSUME DS:GDTSeg
         ;-----------------
         mov   ax,GDTSeg
         mov   ds,ax
         ;初始化全局描述符表
         mov   bx,16
         mov   ax,CodeKSeg
         mul   bx
         mov   CodeK.BaseL,ax
         mov   CodeK.BaseM,dl
         mov   CodeK.BaseH,dh
         mov   ax,LDTSeg
         mul   bx
         mov   LDTable.BaseL,ax
         mov   LDTable.BaseM,dl
         mov   LDTable.BaseH,dh
         ;设置GDT伪描述符
         ASSUME DS:RDataSeg
         mov   ax,RDataSeg
         mov   ds,ax
         mov   ax,GDTSeg
         mul   bx
         mov   WORD PTR VGDTR.Base,ax
         mov   WORD PTR VGDTR.Base+2,dx
         ;初始化演示任务LDT
         cld
         call  Init_MLDT
         ;保存实方式堆栈指针
         mov   SSVar,ss
         mov   SPVar,sp
         ;装载GDTR
         lgdt  QWORD PTR VGDTR
         cli
         ;切换到保护方式
         mov   eax,cr0
         or   al,1
         mov   cr0,eax
         JUMP16 <CodeK_Sel>,<OFFSET Virtual1>
Real:      ;又回到实方式
         mov   ax,RDataSeg
         mov   ds,ax
         lss   sp,DWORD PTR SPVar
         sti
         mov   ax,4c00h
         int   21h
Start      ENDP
;----------------------------------------------------------------------------
Init_MLDT    PROC
         push  ds
         mov   ax,LDTSeg
         mov   ds,ax
         mov   cx,LDNum
         mov   si,OFFSET LDT
InitL:     mov   ax,[si].BaseL
         movzx  eax,ax
         shl   eax,4
         shld  edx,eax,16
         mov   [si].BaseL,ax
         mov   [si].BaseM,dl
         mov   [si].BaseH,dh
         add   si,SIZE Desc
         loop  InitL
         pop   ds
         ret
Init_MLDT    ENDP
;----------------------------------------------------------------------------
RCodeSeg    ENDS
         END   Start

上一页  1 2 

Tags:汇编 教程 控制

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