保护方式JUMP步科 宏指令手册如何把段选择子装入CS

查看:1550|回复:2
助理工程师
本文介绍两个实现实模式与保护模式切换的实例,通过他们说明如何实现实模式与保护模式的切换, 也说明保护模式下的80386及其编程。
&一&演示实模式和保护模式切换的实例(实例一)
实例一的逻辑功能是,以十六进制数的形式显示从内存地址110000H开始的256个字节的值。本实例指定该内存区域的目的仅仅是想说明切换到保护模式的必要性,因为在实模式下不能访问该指定内存区域,只有在保护模式下才能访问到该指定区域。
本实例的具体实现步骤是:(1)作切换到保护方式的准备;(2)切换到保护方式;(3)把指定内存区域的内容传送到位于常规内存的缓冲区中;(4)切换回实模式;(5)显示缓冲区内容。
1.包含文件
386保护模式汇编语言程序用到的包含文件如下所示,该包含文件在后面的程序中还要用到。
;名称:386SCD.INC
;功能:符号常量等的定义
;----------------------------------------------------------------------------
;IFNDEF& && && &__386SCD_INC
;__386SCD_INC& &EQU& &&&1
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
;打开A20地址线
;----------------------------------------------------------------------------
EnableA20& && & MACRO
& && && && && & push& & ax
& && && && && & in& && &al,92h
& && && && && & or& && &al,b
& && && && && & out& &&&92h,al
& && && && && & pop& &&&ax
& && && && && & ENDM
;----------------------------------------------------------------------------
;关闭A20地址线
;----------------------------------------------------------------------------
DisableA20& && &MACRO
& && && && && & push& & ax
& && && && && & in& && &al,92h
& && && && && & and& &&&al,b
& && && && && & out& &&&92h,al
& && && && && & pop& &&&ax
& && && && && & ENDM
;----------------------------------------------------------------------------
;16位偏移的段间直接转移指令的宏定义(在16位代码段中使用)
;----------------------------------------------------------------------------
JUMP16& && && & MACRO& &Selector,Offset
& && && && && & DB& && &0eah& &&&;操作码
& && && && && & DW& && &Offset& &;16位偏移量
& && && && && & DW& && &S段值或段选择子
& && && && && & ENDM
;----------------------------------------------------------------------------
;32位偏移的段间直接转移指令的宏定义(在32位代码段中使用)
;----------------------------------------------------------------------------
COMMENT &JUMP32&
JUMP32& && && & MACRO& &Selector,Offset
& && && && && & DB& && &0eah& &&&;操作码
& && && && && & DD& && &OFFSET
& && && && && & DW& && &S段值或段选择子
& && && && && & ENDM
;-------------------------------------------------
JUMP32& && && & MACRO& &Selector,Offset
& && && && && & DB& && &0eah& &&&;操作码
& && && && && & DW& && &OFFSET
& && && && && & DW& && &0
& && && && && & DW& && &S段值或段选择子
& && && && && & ENDM
;----------------------------------------------------------------------------
;16位偏移的段间调用指令的宏定义(在16位代码段中使用)
;----------------------------------------------------------------------------
CALL16& && && & MACRO& &Selector,Offset
& && && && && & DB& && &9ah& && &;操作码
& && && && && & DW& && &Offset& &;16位偏移量
& && && && && & DW& && &S段值或段选择子
& && && && && & ENDM
;----------------------------------------------------------------------------
;32位偏移的段间调用指令的宏定义(在32位代码段中使用)
;----------------------------------------------------------------------------
COMMENT &CALL32&
CALL32& && && & MACRO& &Selector,Offset
& && && && && & DB& && &9ah& && &;操作码
& && && && && & DD& && &Offset
& && && && && & DW& && &S段值或段选择子
& && && && && & ENDM
;-------------------------------------------------
CALL32& && && & MACRO& &Selector,Offset
& && && && && & DB& && &9ah& && &;操作码
& && && && && & DW& && &Offset
& && && && && & DW& && &0
& && && && && & DW& && &S段值或段选择子
& && && && && & ENDM
;----------------------------------------------------------------------------
;存储段描述符结构类型定义
;----------------------------------------------------------------------------
Desc& && && && &STRUC
LimitL& && && & DW& && &0 ;段界限(BIT0-15)
BaseL& && && &&&DW& && &0 ;段基地址(BIT0-15)
BaseM& && && &&&DB& && &0 ;段基地址(BIT16-23)
Attributes& && &DB& && &0 ;段属性
LimitH& && && & DB& && &0 ;段界限(BIT16-19)(含段属性的高4位)
BaseH& && && &&&DB& && &0 ;段基地址(BIT24-31)
Desc& && && && &ENDS
;----------------------------------------------------------------------------
;门描述符结构类型定义
;----------------------------------------------------------------------------
Gate& && && && &STRUC
OffsetL& && && &DW& && &0 ;32位偏移的低16位
Selector& && &&&DW& && &0 ;选择子
DCount& && && & DB& && &0 ;双字计数
GType& && && &&&DB& && &0 ;类型
OffsetH& && && &DW& && &0 ;32位偏移的高16位
Gate& && && && &ENDS
;----------------------------------------------------------------------------
;伪描述符结构类型定义(用于装入全局或中断描述符表寄存器)
;----------------------------------------------------------------------------
PDesc& && && &&&STRUC
Limit& && && &&&DW& && &0 ;16位界限
Base& && && && &DD& && &0 ;32位基地址
PDesc& && && &&&ENDS
;----------------------------------------------------------------------------
;任务状态段结构类型定义
;----------------------------------------------------------------------------
TSS& && && && & STRUC
TRLink& && && & DW& && &0& && &;链接字段
& && && && && & DW& && &0& && &;不使用,置为0
TRESP0& && && & DD& && &0& && &;0级堆栈指针
TRSS0& && && &&&DW& && &0& && &;0级堆栈段寄存器
& && && && && & DW& && &0& && &;不使用,置为0
TRESP1& && && & DD& && &0& && &;1级堆栈指针
TRSS1& && && &&&DW& && &0& && &;1级堆栈段寄存器
& && && && && & DW& && &0& && &;不使用,置为0
TRESP2& && && & DD& && &0& && &;2级堆栈指针
TRSS2& && && &&&DW& && &0& && &;2级堆栈段寄存器
& && && && && & DW& && &0& && &;不使用,置为0
TRCR3& && && &&&DD& && &0& && &;CR3
TREIP& && && &&&DD& && &0& && &;EIP
TREFlag& && && &DD& && &0& && &;EFLAGS
TREAX& && && &&&DD& && &0& && &;EAX
TRECX& && && &&&DD& && &0& && &;ECX
TREDX& && && &&&DD& && &0& && &;EDX
TREBX& && && &&&DD& && &0& && &;EBX
TRESP& && && &&&DD& && &0& && &;ESP
TREBP& && && &&&DD& && &0& && &;EBP
TRESI& && && &&&DD& && &0& && &;ESI
TREDI& && && &&&DD& && &0& && &;EDI
TRES& && && && &DW& && &0& && &;ES
& && && && && & DW& && &0& && &;不使用,置为0
TRCS& && && && &DW& && &0& && &;CS
& && && && && & DW& && &0& && &;不使用,置为0
TRSS& && && && &DW& && &0& && &;SS
& && && && && & DW& && &0& && &;不使用,置为0
TRDS& && && && &DW& && &0& && &;DS
& && && && && & DW& && &0& && &;不使用,置为0
TRFS& && && && &DW& && &0& && &;FS
& && && && && & DW& && &0& && &;不使用,置为0
TRGS& && && && &DW& && &0& && &;GS
& && && && && & DW& && &0& && &;不使用,置为0
TRLDTR& && && & DW& && &0& && &;LDTR
& && && && && & DW& && &0& && &;不使用,置为0
TRTrip& && && & DW& && &0& && &;调试陷阱标志(只用位0)
TRIOMap& && && &DW& && &$+2& & ;指向I/O许可位图区的段内偏移
TSS& && && && & ENDS
;----------------------------------------------------------------------------
;存储段描述符类型值说明
;----------------------------------------------------------------------------
ATDR& && && && &EQU& &&&90存在的只读数据段类型值
ATDW& && && && &EQU& &&&92存在的可读写数据段属性值
ATDWA& && && &&&EQU& &&&93存在的已访问可读写数据段类型值
ATCE& && && && &EQU& &&&98存在的只执行代码段属性值
ATCER& && && &&&EQU& &&&9存在的可执行可读代码段属性值
ATCCO& && && &&&EQU& &&&9存在的只执行一致代码段属性值
ATCCOR& && && & EQU& &&&9存在的可执行可读一致代码段属性值
;----------------------------------------------------------------------------
;系统段描述符类型值说明
;----------------------------------------------------------------------------
ATLDT& && && &&&EQU& &&&82局部描述符表段类型值
ATTaskGate& && &EQU& &&&85任务门类型值
AT386TSS& && &&&EQU& &&&89可用386任务状态段类型值
AT386CGate& && &EQU& &&&8386调用门类型值
AT386IGate& && &EQU& &&&8386中断门类型值
AT386TGate& && &EQU& &&&8386陷阱门类型值
;----------------------------------------------------------------------------
;DPL值说明
;----------------------------------------------------------------------------
DPL0& && && && &EQU& &&&00DPL=0
DPL1& && && && &EQU& &&&20DPL=1
DPL2& && && && &EQU& &&&40DPL=2
DPL3& && && && &EQU& &&&60DPL=3
;----------------------------------------------------------------------------
;RPL值说明
;----------------------------------------------------------------------------
RPL0& && && && &EQU& &&&00RPL=0
RPL1& && && && &EQU& &&&01RPL=1
RPL2& && && && &EQU& &&&02RPL=2
RPL3& && && && &EQU& &&&03RPL=3
;----------------------------------------------------------------------------
;IOPL值说明
;----------------------------------------------------------------------------
IOPL0& && && &&&EQU& &&&0000IOPL=0
IOPL1& && && &&&EQU& &&&1000IOPL=1
IOPL2& && && &&&EQU& &&&2000IOPL=2
IOPL3& && && &&&EQU& &&&3000IOPL=3
;----------------------------------------------------------------------------
;其它常量值说明
;----------------------------------------------------------------------------
D32& && && && & EQU& &&&40h& && & ;32位代码段标志
GL& && && && &&&EQU& &&&80h& && & ;段界限以4K为单位标志
TIL& && && && & EQU& &&&04h& && & ;TI=1(局部描述符表标志)
VMFL& && && && &EQU& &&&VMF=1
VMFLW& && && &&&EQU& &&&0002h
IFL& && && && & EQU& &&&IF=1
RFL& && && && & EQU& &&&RF=1(重启动标志,为1表示忽略调试故障)
RFLW& && && && &EQU& &&&0001h
NTL& && && && & EQU& &&&NT=1
;----------------------------------------------------------------------------
;分页机制使用的常量说明
;----------------------------------------------------------------------------
PL& && && && &&&EQU& &&&1& &&&;页存在属性位
RWR& && && && & EQU& &&&0& &&&;R/W属性位值,读/执行
RWW& && && && & EQU& &&&2& &&&;R/W属性位值,读/写/执行
USS& && && && & EQU& &&&0& &&&;U/S属性位值,系统级
USU& && && && & EQU& &&&4& &&&;U/S属性位值,用户级
;----------------------------------------------------------------------------
2.实例源程序
实例一的源程序如下所示:
;名称:ASM1.ASM
;功能:演示实方式和保护方式切换(切换到16位代码段)
;----------------------------------------------------------------------------
INCLUDE& && && &386SCD.INC
;----------------------------------------------------------------------------
;字符显示宏指令的定义
;----------------------------------------------------------------------------
EchoCh& && && & MACRO& &ascii
& && && && && & mov& &&&ah,2
& && && && && & mov& &&&dl,ascii
& && && && && & int& &&&21h
& && && && && & ENDM
;----------------------------------------------------------------------------
DSEG& && && && &SEGMENT USE16& && && && && &&&;16位数据段
;----------------------------------------------------------------------------
GDT& && && && & LABEL& &BYTE& && && && && && &;全局描述符表
DUMMY& && && &&&Desc& & &&& && && && && && &&&;空描述符
Code& && && && &Desc& & &0ffffh,,,ATCE,,&& &&&;代码段描述符
DataS& && && &&&Desc& & &0ffffh,0,11h,ATDW,,& ;源数据段描述符
DataD& && && &&&Desc& & &0ffffh,,,ATDW,,&& &&&;目标数据段描述符
;----------------------------------------------------------------------------
GDTLen& && && & =& && & $-GDT& && && && && &&&;全局描述符表长度
VGDTR& && && &&&PDesc& &&GDTLen-1,&& && && &&&;伪描述符
;----------------------------------------------------------------------------
Code_Sel& && &&&=& && & Code-GDT& && && && &&&;代码段选择子
DataS_Sel& && & =& && & Datas-GDT& && && && & ;源数据段选择子
DataD_Sel& && & =& && & DataD-GDT& && && && & ;目标数据段选择子
;----------------------------------------------------------------------------
BufLen& && && & =& && & 256& && && && && && & ;缓冲区字节长度
Buffer& && && & DB& && &BufLen DUP(0)& && && &;缓冲区
;----------------------------------------------------------------------------
DSEG& && && && &ENDS& && && && && && && && &&&;数据段定义结束
;----------------------------------------------------------------------------
CSEG& && && && &SEGMENT USE16& && && && && &&&;16位代码段
& && && && && & ASSUME&&CS:CSEG,DS:DSEG
;----------------------------------------------------------------------------
Start& && && &&&PROC
& && && && && & mov& &&&ax,DSEG
& && && && && & mov& &&&ds,ax
& && && && && & ;准备要加载到GDTR的伪描述符
& && && && && & mov& &&&bx,16
& && && && && & mul& &&&bx
& && && && && & add& &&&ax,OFFSET GDT& && && & ;计算并设置基地址
& && && && && & adc& &&&dx,0& && && && && && & ;界限已在定义时设置好
& && && && && & mov& &&&WORD PTR VGDTR.Base,ax
& && && && && & mov& &&&WORD PTR VGDTR.Base+2,dx
& && && && && & ;设置代码段描述符
& && && && && & mov& &&&ax,cs
& && && && && & mul& &&&bx
& && && && && & mov& &&&WORD PTR Code.BaseL,代码段开始偏移为0
& && && && && & mov& &&&BYTE PTR Code.BaseM,代码段界限已在定义时设置好
& && && && && & mov& &&&BYTE PTR Code.BaseH,dh
& && && && && & ;设置目标数据段描述符
& && && && && & mov& &&&ax,ds
& && && && && & mul& &&&bx& && && && && && && &;计算并设置目标数据段基址
& && && && && & add& &&&ax,OFFSET Buffer
& && && && && & adc& &&&dx,0
& && && && && & mov& &&&WORD PTR DataD.BaseL,ax
& && && && && & mov& &&&BYTE PTR DataD.BaseM,dl
& && && && && & mov& &&&BYTE PTR DataD.BaseH,dh
& && && && && & ;加载GDTR
& && && && && & lgdt& & QWORD PTR VGDTR
& && && && && & cli& && && && && && && && && & ;关中断
& && && && && & EnableA20& && && && && && && & ;打开地址线A20
& && && && && & ;切换到保护方式
& && && && && & mov& &&&eax,cr0
& && && && && & or& && &eax,1
& && && && && & mov& &&&cr0,eax
& && && && && & ;清指令预取队列,并真正进入保护方式
& && && && && & JUMP16&&Code_Sel,&OFFSET Virtual&
Virtual:& && &&&;现在开始在保护方式下运行
& && && && && & mov& &&&ax,DataS_Sel
& && && && && & mov& &&&ds,ax& && && && && && &;加载源数据段描述符
& && && && && & mov& &&&ax,DataD_Sel
& && && && && & mov& &&&es,ax& && && && && && &;加载目标数据段描述符
& && && && && & cld
& && && && && & xor& &&&si,si
& && && && && & xor& &&&di,di& && && && && && &;设置指针初值
& && && && && & mov& &&&cx,BufLen/4& && && && &;设置4字节为单位的缓冲区长度
& && && && && & repz& & movsd& && && && && && &;传送
& && && && && & ;切换回实模式
& && && && && & mov& &&&eax,cr0
& && && && && & and& &&&al,b
& && && && && & mov& &&&cr0,eax
& && && && && & ;清指令预取队列,进入实方式
& && && && && & JUMP16&&&SEG Real&,&OFFSET Real&
Real:& && && &&&;现在又回到实方式
& && && && && & DisableA20
& && && && && & sti
& && && && && & mov& &&&ax,DSEG
& && && && && & mov& &&&ds,ax
& && && && && & mov& &&&si,OFFSET Buffer
& && && && && & cld
& && && && && & mov& &&&bp,BufLen/16
NextLine:& && & mov& &&&cx,16
NextCh:& && && &lodsb
& && && && && & push& & ax
& && && && && & shr& &&&al,1
& && && && && & call& & ToASCII
& && && && && & EchoCh&&al
& && && && && & pop& &&&ax
& && && && && & call& & ToASCII
& && && && && & EchoCh&&al
& && && && && & EchoCh&&' '
& && && && && & loop& & NextCh
& && && && && & EchoCh&&0dh
& && && && && & EchoCh&&0ah
& && && && && & dec& &&&bp
& && && && && & jnz& &&&NextLine
& && && && && & mov& &&&ax,4c00h
& && && && && & int& &&&21h
Start& && && &&&ENDP
;----------------------------------------------------------------------------
ToASCII& && && &PROC
& && && && && & and& &&&al,0fh
& && && && && & add& &&&al,90h
& && && && && & daa
& && && && && & adc& &&&al,40h
& && && && && & daa
& && && && && & ret
ToASCII& && && &ENDP
;----------------------------------------------------------------------------
CSEG& && && && &ENDS& && && && && && && && && &;代码段定义结束
;----------------------------------------------------------------------------
& && && && && & END& &&&Start
3.关于实例步骤的注释
在源程序的开头首先包含了文件“386SCD.INC”,在此包含文件中定义了保护模式程序设计要用到的一些结构、宏及常量。下面对各实现步骤作些说明。
(1)切换到保护方式的准备工作
在从实模式切换到保护模式之前,必须作必要的准备。准备工作的内容根据实际而定。最起码的准备工作是建立合适的全局描述符表,并使用GDTR指向该GDT。因为在切换到保护方式时,至少要把代码段的选择子装载到CS,所以GDT中至少含有代码段的描述符。
从本实例源程序可见,全局描述符表GDT仅有四个描述符:第一个是空描述符;第二个是代码段描述符;第三个和第四个分别为源数据段及目标数据段描述符。本实例各描述符中的段界限是在定义时设置的,并且除伪描述符VGDTR中的界限按GDT的实际长度设置外,各使用的存储段描述符的界限都规定为0FFFFH。另外,描述符中的段属性也根据所描述段的类型被预置,各属性的定义在包含文件386SCD.INC中均有说明。从属性值可知,这三个段都是16位段。
由于在切换到保护方式后就要引用GDT,所以在切换到保护方式前必须装载GDTR。实例中使用如下指令装载GDTR:
& & LGDT&&QWORD PTR VGDTR
该指令的功能是把存储器中的伪描述符VGDTR装入到全局描述符表寄存器GDTR中。伪描述符VGDTR的结构如前所述结构类型PDESC所示,低字是以字节位单位的全局描述符表段的界限,高双字为描述符表段的线性基地址(本实例不启用分页机制,所以线性地址等同于物理地址)。本实例中未涉及到局部描述符表及中断描述符表,后面的文章将作详细说明。
(2)由实模式切换到保护模式
在做好准备后,从实模式切换到保护模式并不难。原则上只要把控制寄存器CR0中的PE位置1即可。本实例采用如下三条指令设置PE位:
& & mov& &&&eax,cr0
& & or& && &eax,1
& & mov& &&&cr0,eax
实际情况要比这复杂些。执行上面的三条指令后,处理器转入保护模式,但CS中的内容还是实模式下代码段的段值,而不是保护模式下代码段的选择子,所以在取指令之前得把代码段的选择子装入CS。为此,紧接着这三条指令,安排一条如下所示的段间转移指令:
& & JUMP16&&Code_Sel,&OFFSET Virtual&
这条段间转移指令在实模式下被预取并在保护方式下被执行。利用这条段间转移指令可把保护模式下代码段的选择子装入CS,同时也刷新指令预取队列。从此真正进入保护模式。
(3)由保护模式切换到实模式
在80386上,从保护模式切换到实模式的过程类似于从实模式切换到保护模式。原则上只要把控制寄存器CR0中的PE位清0即可。实际上,在此之后也要安排一条段间转移指令,一方面清指令预取队列,另一方面把实模式下代码段的段值送CS。这条段间转移指令在保护方式下被预取并在实模式下被执行。
(4)保护模式下的数据传送
首先,把源数据段和目标数据段的选择子装入DS和ES寄存器,这两个描述符已在实模式下设置好,把选择子装入段寄存器就意味着把包括基地址在内的段信息装入到了段描述符高速缓冲寄存器。然后设置指针寄存器SI和DI的初值,也设置计数器CX的初值。根据预置的段属性,在保护方式下,代码段也仅是16位段,串操作指令只使用16位的SI、DI和CX等寄存器。最后利用串操作指令实施传送。
(5)显示缓冲区中的内容
由于缓冲区在常规内存中,所以在实模式下根据要求按十六进制显示其内容是很容易理解的,这里就不再多说。
4.内存映象
在源程序中没有把GDT作为一个单独的段对待,但在进入保护方式后,它是一个独立的段。从对代码段和源数据段描述符所赋的基地址和段界限值可见,代码段和数据段有部分覆盖。尽管这样做不利于代码和数据的安全,但如果需要,这样做是可行的。本实例运行时的内存映象如下图所示。
助理工程师
5.特别说明
作为第一个实模式和保护模式切换的例子,本实例作了大量的简化处理。
通常,由实模式切换到保护模式的准备工作还应包含建立中断描述符表。但本实例没有建立中断描述符表。为此,要求整个过程在关中断的情况下进行;要求不使用软中断指令;假设不发生任何异常。否则会导致系统崩溃。
本实例未使用局部描述符表,所以在进入保护模式后没有设置局部描述符表寄存器LDTR。为此,在保护模式下使用的段选择子都指定GDT中的描述符。
本实例未定义保护模式下的堆栈段,GDT中没有堆栈段描述符,在保护模式下没有设置SS,所以在保护方式下没有涉及堆栈操作的指令。
本实例各描述符特权级DPL和各选择子的请求特权级RPL均为0,在保护方式下运行时的当前特权级CPL也是0。
本实例没有采用分页管理机制,也即CR0中的PG位为0,线性地址就是存储单元的物理地址。
6.打开和关闭地址线A20
PC及其兼容机的第21根地址线(A20)较特殊,计算机系统中一般安排一个 “门”控制该地址线是否有效。为了访问地址在1M以上的存储单元,应先打开控制地址线A20的“门”。这种设置与实模式下只使用最低端的1M字节存储空间有关,与处理器是否工作在实模式或保护方式无关,即使在关闭地址线A20时,也可进入保护模式。
如何打开和关闭地址线A20与计算机系统的具体设置有关。在本文中介绍的包含文件386SCD.INC中定义了两个宏,打开地址线A20的宏EnableA20和关闭地址线A20的宏DisableA20,此两个宏指令在一般的PC兼容机上都是可行的。
&二&演示32位代码段和16位代码段切换的实例(实例二)
实例二的逻辑功能是,以十六进制数和ASCII字符两种形式显示从内存地址100000H开始的16个字节的内容。
从功能上看,本实例类似于实例一,但在实现方法上却有了改变,它更能反映出实模式和保护模式切换的情况。具体实现步骤是:(1)作切换到保护方式的准备;(2)切换到保护方式的一个32位代码段;(3)把指定内存区域的内容以字节为单位,转换成对应的十六进制数的ASCII码,并直接填入显示缓冲区实现显示;(4)再变换到保护方式下的一个16位代码段;(5)把指定内存区域的内容直接作为ASCII码填入显示缓冲区中实现显示;(6)切换回实模式。
1.实例二源程序
实例二的源程序如下所示:
;名称:ASM2.ASM
;功能:演示实方式和保护方式切换(切换到32位代码段)
;----------------------------------------------------------------------------
INCLUDE& && && &386SCD.INC
;----------------------------------------------------------------------------
DSEG& && && && &SEGMENT USE16& && && && && && && &;16位数据段
;----------------------------------------------------------------------------
GDT& && && && & LABEL& &BYTE& && && && && && && & ;全局描述符表
DUMMY& && && &&&Desc& & &&& && && && && && && && &;空描述符
Normal& && && & Desc& & &0ffffh,,,ATDW,,&& && && &;规范段描述符
Code32& && && & Desc& & &C32Len-1,,,ATCE,D32,&& & ;32位代码段描述符
Code16& && && & Desc& & &0ffffh,,,ATCE,,&& && && &;16位代码段描述符
DataS& && && &&&Desc& & &DataLen-1,0,10h,ATDR,,&&&;源数据段描述符
DataD& && && &&&Desc& & &h,0bh,ATDW,,&& &;显示缓冲区描述符
Stacks& && && & Desc& & &StackLen-1,,,ATDW,,&& &&&;堆栈段描述符
;----------------------------------------------------------------------------
GDTLen& && && & =& && & $-GDT& && && && && && && &;全局描述符表长度
VGDTR& && && &&&PDesc& &&GDTLen-1,&& && && && && &;伪描述符
;----------------------------------------------------------------------------
SaveSP& && && & DW& && &?& && && && && && && && & ;用于保存SP寄存器
SaveSS& && && & DW& && &?& && && && && && && && & ;用于保存SS寄存器
;----------------------------------------------------------------------------
Normal_Sel& && &=& && & Normal-GDT& && && && && & ;规范段描述符选择子
Code32_Sel& && &=& && & Code32-GDT& && && && && & ;32位代码段选择子
Code16_Sel& && &=& && & Code16-GDT& && && && && & ;16位代码段选择子
DataS_Sel& && & =& && & Datas-GDT& && && && && &&&;源数据段选择子
DataD_Sel& && & =& && & DataD-GDT& && && && && &&&;目标数据段选择子
Stacks_Sel& && &=& && & Stacks-GDT& && && && && & ;堆栈段描述符选择子
;----------------------------------------------------------------------------
DataLen& && && &=& && & 16
;----------------------------------------------------------------------------
DSEG& && && && &ENDS& && && && && && && && && && &;数据段定义结束
;----------------------------------------------------------------------------
StackSeg& && &&&SEGMENT PARA STACK USE16
StackLen& && &&&=& && & 256
& && && && && & DB& && &StackLen DUP(0)
StackSeg& && &&&ENDS
;----------------------------------------------------------------------------
CSEG1& && && &&&SEGMENT USE16 'REAL'& && && && &&&;16位代码段
& && && && && & ASSUME&&CS:CSEG1,DS:DSEG
;----------------------------------------------------------------------------
Start& && && &&&PROC
& && && && && & mov& &&&ax,DSEG
& && && && && & mov& &&&ds,ax
& && && && && & ;准备要加载到GDTR的伪描述符
& && && && && & mov& &&&bx,16
& && && && && & mul& &&&bx
& && && && && & add& &&&ax,OFFSET GDT& && && && & ;计算并设置基地址
& && && && && & adc& &&&dx,0& && && && && && && & ;界限已在定义时设置好
& && && && && & mov& &&&WORD PTR VGDTR.Base,ax
& && && && && & mov& &&&WORD PTR VGDTR.Base+2,dx
& && && && && & ;设置32位代码段描述符
& && && && && & mov& &&&ax,CSEG2
& && && && && & mul& &&&bx
& && && && && & mov& &&&WORD PTR Code32.BaseL,ax
& && && && && & mov& &&&BYTE PTR Code32.BaseM,dl
& && && && && & mov& &&&BYTE PTR Code32.BaseH,dh
& && && && && & ;设置16位代码段描述符
& && && && && & mov& &&&ax,CSEG3
& && && && && & mul& &&&bx
& && && && && & mov& &&&WORD PTR Code16.BaseL,ax&&;代码段开始偏移为0
& && && && && & mov& &&&BYTE PTR Code16.BaseM,dl&&;代码段界限已在定义时设置好
& && && && && & mov& &&&BYTE PTR Code16.BaseH,dh
& && && && && & ;设置堆栈段描述符
& && && && && & mov& &&&ax,ss
& && && && && & mov& &&&WORD PTR SaveSS,ax
& && && && && & mov& &&&WORD PTR SaveSP,sp
& && && && && & mov& &&&ax,StackSeg
& && && && && & mul& &&&bx
& && && && && & mov& &&&WORD PTR Stacks.BaseL,ax
& && && && && & mov& &&&BYTE PTR Stacks.BaseM,dl
& && && && && & mov& &&&BYTE PTR Stacks.BaseH,dh
& && && && && & ;加载GDTR
& && && && && & lgdt& & QWORD PTR VGDTR
& && && && && & cli& && && && && && && && && && & ;关中断
& && && && && & EnableA20& && && && && && && && & ;打开地址线A20
& && && && && & ;切换到保护方式
& && && && && & mov& &&&eax,cr0
& && && && && & or& && &al,1
& && && && && & mov& &&&cr0,eax
& && && && && & ;清指令预取队列,并真正进入保护方式
& && && && && & JUMP16&&Code32_Sel,&OFFSET SPM32&
ToReal:& && && &;现在又回到实方式
& && && && && & mov& &&&ax,DSEG
& && && && && & mov& &&&ds,ax
& && && && && & mov& &&&sp,SaveSP
& && && && && & mov& &&&ss,SaveSS
& && && && && & DisableA20
& && && && && & sti
& && && && && & mov& &&&ax,4c00h
& && && && && & int& &&&21h
Start& && && &&&ENDP
;----------------------------------------------------------------------------
CSEG1& && && &&&ENDS& && && && && && && && && && &;代码段定义结束
;----------------------------------------------------------------------------
CSEG2& && && &&&SEGMENT USE32 'PM32'
& && && && && & ASSUME&&CS:CSEG2
;----------------------------------------------------------------------------
SPM32& && && &&&PROC
& && && && && & mov& &&&ax,Stacks_Sel
& && && && && & mov& &&&ss,ax
& && && && && & mov& &&&esp,StackLen
& && && && && & mov& &&&ax,DataS_Sel
& && && && && & mov& &&&ds,ax
& && && && && & mov& &&&ax,DataD_Sel
& && && && && & mov& &&&es,ax
& && && && && & xor& &&&esi,esi
& && && && && & xor& &&&edi,edi
& && && && && & mov& &&&ecx,DataLen
& && && && && & cld
Next:& && && &&&lodsb
& && && && && & push& & ax
& && && && && & CALL& & ToASCII
& && && && && & mov& &&&ah,7
& && && && && & shl& &&&eax,16
& && && && && & pop& &&&ax
& && && && && & shr& &&&al,4
& && && && && & CALL& & ToASCII
& && && && && & mov& &&&ah,7
& && && && && & stosd
& && && && && & mov& &&&al,20h
& && && && && & stosw
& && && && && & loop& & Next
& && && && && & JUMP32& &Code16_Sel,&OFFSET SPM16&
SPM32& && && &&&ENDP
;----------------------------------------------------------------------------
ToASCII& && && &PROC
& && && && && & and& &&&al,b
& && && && && & add& &&&al,30h
& && && && && & cmp& &&&al,39h
& && && && && & jbe& &&&Isdig
& && && && && & add& &&&al,7
IsDig:& && && & ret
ToASCII& && && &ENDP
;----------------------------------------------------------------------------
C32Len& && && & =& && & $
;----------------------------------------------------------------------------
CSEG2& && && &&&ENDS
;----------------------------------------------------------------------------
CSEG3& && && &&&SEGMENT USE16 'PM16'
& && && && && & ASSUME&&CS:CSEG3
;----------------------------------------------------------------------------
SPM16& && && &&&PROC
& && && && && & xor& &&&si,si
& && && && && & mov& &&&di,DataLen*3*2
& && && && && & mov& &&&ah,7
& && && && && & mov& &&&cx,DataLen
AGain:& && && & lodsb
& && && && && & stosw
& && && && && & loop& & AGain
& && && && && & mov& &&&ax,Normal_sel
& && && && && & mov& &&&ds,ax
& && && && && & mov& &&&es,ax
& && && && && & mov& &&&ss,ax
& && && && && & mov& &&&eax,cr0
& && && && && & and& &&&al,b
& && && && && & mov& &&&cr0,eax
& && && && && & jmp& &&&FAR PTR ToReal
SPM16& && && &&&ENDP
;----------------------------------------------------------------------------
CSEG3& && && &&&ENDS
;----------------------------------------------------------------------------
& && && && && & END& &&&Start
2.关于实现步骤的注释
(1)切换到保护模式的准备工作
建立全局描述符表,这里的全局描述符表含有两个16位数据段的描述符、一个16位代码段的描述符和一个16位的堆栈段描述符。此外,GDT中还有一个32位的代码段描述符,描述32位代码段,该描述符的属性字段中的D位为1。
(2)由实模式切换到保护模式
由实模式切换到保护模式32位代码段的方法与切换到16位代码段的方法相同。由保护模式16位代码段切换回实模式的方法与实例一相似。
在保护模式下,通过如下直接段间转移指令从32位代码段切换到16位代码段:
& & JUMP32& &Code16_Sel,&OFFSET SPM16&
从该宏指令的定义可知,该转移指令含48位指针,其高16位是16位代码段的选择子,低32位是16位代码段的入口偏移。该指令在32位方式下预取并执行。由于在32位方式下执行,所以要使用48位指针。
(3)显示指定内存区域的内容
在本实例中,采用直接写显示缓冲区的方法实现显示。假设显示缓冲区的开始物理地址是0B8000H, 3号文本显示模式,在屏幕的第一行进行显示。
3.特别说明
本实例在保护方式下使用了涉及堆栈操作的指令,因此建立了一个16位的保护模式下的堆栈段。
本实例仍作了大量的简化处理。如:没有建立IDT和LDT等,各特权级均是0。也没有采用分页管理机制。
从本实例的GDT中可见,两个数据段的界限都是根据实际大小而设置的。从源程序代码段CSEG3可见,在切换到实模式之前,把一个指向似乎没有用的数据段的描述符Normal的选择子装载到DS和ES。这是为什么呢?
内容 段寄存器 段基地址 段界限(固定) 段属性(固定)
存在性 特权级 已存取 粒度 扩展方向 可读性 可写性 可执行 堆栈大小 一致特权
CS 当前CS*16 0000FFFFH Y 0 Y B U Y Y Y - N
SS 当前SS*16 0000FFFFH Y 0 Y B U Y Y N W -
DS 当前DS*16 0000FFFFH Y 0 Y B U Y Y N - -
ES 当前ES*16 0000FFFFH Y 0 Y B U Y Y N - -
FS 当前FS*16 0000FFFFH Y 0 Y B U Y Y N - -
GS 当前GS*16 0000FFFFH Y 0 Y B U Y Y N - -
在分段管理机制一文中已介绍过,每个段寄存器都配有段描述符高速缓冲寄存器,这些高速缓冲寄存器在实方式下仍发挥作用,只是内容上与保护模式下有所不同。如上表所示,其中“Y”表示“是”; “N”表示“否”;“B”表示字节;“U”表示向上扩展,“W”表示以字方式操作堆栈。段基地址仍是 32位,其值是相应段寄存器值(段值)乘以16,在把段值装载到段寄存器时刷新。由于其值是16位段值乘上16,所以在实模式下基地址实际上有效位只有20位。每个段的32位段界限都固定为0FFFFH,段属性的许多位也是固定的。所谓固定是指在实方式下不可设置这些属性值,只能继续沿用保护方式下所设置的值。因此,在准备结束保护模式回到实模式之前,要通过加载一个合适的描述符选择子到有关段寄存器,以使得对应段描述符高速缓冲寄存器中含有合适的段界限和属性。本实例GDT中的描述符Normal就是这样一个描述符,在返回实模式之前把对应选择子Normal_Sel加载到DS和ES就是此目的。由于SS段描述符中的内容已符合实模式的需要,所以尽管也改变了SS,但不需要重新加载SS(本实例中重新加载了SS,这除了稍增加运行时间外,并没有什么坏处)。16位代码段描述符中的内容也符合实模式的需要,所以在通过16位代码段返回实模式时,CS段描述符中的内容也符合实模式的要求。需要注意的是,不能从32位代码段返回实模式,这是因为无法实现从32位代码段返回时CS高速缓冲寄存器中的属性符合实模式的要求(实模式不能改变段属性)。顺便说以下,实例一中的描述符都是符合实模式要求的。段描述符高速缓冲寄存器中含有合适的段界限
4.关于32位代码段程序设计的说明
在32位代码段中,缺省的操作数大小是32位,缺省的存储单元地址大小是32位。由于串操作指令使用的指针寄存器是ESI和EDI,LOOP指令使用的计数器是ECX,所以,在代码段CSEG2中,为了使用串操作指令,对ESI和EDI等寄存器赋初值。请比较代码段CSEG3中的相关片段和实例一中的相关片段,它们是16位代码段。
助理工程师
5.特别说明
作为第一个实模式和保护模式切换的例子,本实例作了大量的简化处理。
通常,由实模式切换到保护模式的准备工作还应包含建立中断描述符表。但本实例没有建立中断描述符表。为此,要求整个过程在关中断的情况下进行;要求不使用软中断指令;假设不发生任何异常。否则会导致系统崩溃。
本实例未使用局部描述符表,所以在进入保护模式后没有设置局部描述符表寄存器LDTR。为此,在保护模式下使用的段选择子都指定GDT中的描述符。
本实例未定义保护模式下的堆栈段,GDT中没有堆栈段描述符,在保护模式下没有设置SS,所以在保护方式下没有涉及堆栈操作的指令。
本实例各描述符特权级DPL和各选择子的请求特权级RPL均为0,在保护方式下运行时的当前特权级CPL也是0。
本实例没有采用分页管理机制,也即CR0中的PG位为0,线性地址就是存储单元的物理地址。
6.打开和关闭地址线A20
PC及其兼容机的第21根地址线(A20)较特殊,计算机系统中一般安排一个 “门”控制该地址线是否有效。为了访问地址在1M以上的存储单元,应先打开控制地址线A20的“门”。这种设置与实模式下只使用最低端的1M字节存储空间有关,与处理器是否工作在实模式或保护方式无关,即使在关闭地址线A20时,也可进入保护模式。
如何打开和关闭地址线A20与计算机系统的具体设置有关。在本文中介绍的包含文件386SCD.INC中定义了两个宏,打开地址线A20的宏EnableA20和关闭地址线A20的宏DisableA20,此两个宏指令在一般的PC兼容机上都是可行的。
&二&演示32位代码段和16位代码段切换的实例(实例二)
实例二的逻辑功能是,以十六进制数和ASCII字符两种形式显示从内存地址100000H开始的16个字节的内容。
从功能上看,本实例类似于实例一,但在实现方法上却有了改变,它更能反映出实模式和保护模式切换的情况。具体实现步骤是:(1)作切换到保护方式的准备;(2)切换到保护方式的一个32位代码段;(3)把指定内存区域的内容以字节为单位,转换成对应的十六进制数的ASCII码,并直接填入显示缓冲区实现显示;(4)再变换到保护方式下的一个16位代码段;(5)把指定内存区域的内容直接作为ASCII码填入显示缓冲区中实现显示;(6)切换回实模式。
1.实例二源程序
实例二的源程序如下所示:
;名称:ASM2.ASM
;功能:演示实方式和保护方式切换(切换到32位代码段)
;----------------------------------------------------------------------------
INCLUDE& && && &386SCD.INC
;----------------------------------------------------------------------------
DSEG& && && && &SEGMENT USE16& && && && && && && &;16位数据段
;----------------------------------------------------------------------------
GDT& && && && & LABEL& &BYTE& && && && && && && & ;全局描述符表
DUMMY& && && &&&Desc& & &&& && && && && && && && &;空描述符
Normal& && && & Desc& & &0ffffh,,,ATDW,,&& && && &;规范段描述符
Code32& && && & Desc& & &C32Len-1,,,ATCE,D32,&& & ;32位代码段描述符
Code16& && && & Desc& & &0ffffh,,,ATCE,,&& && && &;16位代码段描述符
DataS& && && &&&Desc& & &DataLen-1,0,10h,ATDR,,&&&;源数据段描述符
DataD& && && &&&Desc& & &h,0bh,ATDW,,&& &;显示缓冲区描述符
Stacks& && && & Desc& & &StackLen-1,,,ATDW,,&& &&&;堆栈段描述符
;----------------------------------------------------------------------------
GDTLen& && && & =& && & $-GDT& && && && && && && &;全局描述符表长度
VGDTR& && && &&&PDesc& &&GDTLen-1,&& && && && && &;伪描述符
;----------------------------------------------------------------------------
SaveSP& && && & DW& && &?& && && && && && && && & ;用于保存SP寄存器
SaveSS& && && & DW& && &?& && && && && && && && & ;用于保存SS寄存器
;----------------------------------------------------------------------------
Normal_Sel& && &=& && & Normal-GDT& && && && && & ;规范段描述符选择子
Code32_Sel& && &=& && & Code32-GDT& && && && && & ;32位代码段选择子
Code16_Sel& && &=& && & Code16-GDT& && && && && & ;16位代码段选择子
DataS_Sel& && & =& && & Datas-GDT& && && && && &&&;源数据段选择子
DataD_Sel& && & =& && & DataD-GDT& && && && && &&&;目标数据段选择子
Stacks_Sel& && &=& && & Stacks-GDT& && && && && & ;堆栈段描述符选择子
;----------------------------------------------------------------------------
DataLen& && && &=& && & 16
;----------------------------------------------------------------------------
DSEG& && && && &ENDS& && && && && && && && && && &;数据段定义结束
;----------------------------------------------------------------------------
StackSeg& && &&&SEGMENT PARA STACK USE16
StackLen& && &&&=& && & 256
& && && && && & DB& && &StackLen DUP(0)
StackSeg& && &&&ENDS
;----------------------------------------------------------------------------
CSEG1& && && &&&SEGMENT USE16 'REAL'& && && && &&&;16位代码段
& && && && && & ASSUME&&CS:CSEG1,DS:DSEG
;----------------------------------------------------------------------------
Start& && && &&&PROC
& && && && && & mov& &&&ax,DSEG
& && && && && & mov& &&&ds,ax
& && && && && & ;准备要加载到GDTR的伪描述符
& && && && && & mov& &&&bx,16
& && && && && & mul& &&&bx
& && && && && & add& &&&ax,OFFSET GDT& && && && & ;计算并设置基地址
& && && && && & adc& &&&dx,0& && && && && && && & ;界限已在定义时设置好
& && && && && & mov& &&&WORD PTR VGDTR.Base,ax
& && && && && & mov& &&&WORD PTR VGDTR.Base+2,dx
& && && && && & ;设置32位代码段描述符
& && && && && & mov& &&&ax,CSEG2
& && && && && & mul& &&&bx
& && && && && & mov& &&&WORD PTR Code32.BaseL,ax
& && && && && & mov& &&&BYTE PTR Code32.BaseM,dl
& && && && && & mov& &&&BYTE PTR Code32.BaseH,dh
& && && && && & ;设置16位代码段描述符
& && && && && & mov& &&&ax,CSEG3
& && && && && & mul& &&&bx
& && && && && & mov& &&&WORD PTR Code16.BaseL,ax&&;代码段开始偏移为0
& && && && && & mov& &&&BYTE PTR Code16.BaseM,dl&&;代码段界限已在定义时设置好
& && && && && & mov& &&&BYTE PTR Code16.BaseH,dh
& && && && && & ;设置堆栈段描述符
& && && && && & mov& &&&ax,ss
& && && && && & mov& &&&WORD PTR SaveSS,ax
& && && && && & mov& &&&WORD PTR SaveSP,sp
& && && && && & mov& &&&ax,StackSeg
& && && && && & mul& &&&bx
& && && && && & mov& &&&WORD PTR Stacks.BaseL,ax
& && && && && & mov& &&&BYTE PTR Stacks.BaseM,dl
& && && && && & mov& &&&BYTE PTR Stacks.BaseH,dh
& && && && && & ;加载GDTR
& && && && && & lgdt& & QWORD PTR VGDTR
& && && && && & cli& && && && && && && && && && & ;关中断
& && && && && & EnableA20& && && && && && && && & ;打开地址线A20
& && && && && & ;切换到保护方式
& && && && && & mov& &&&eax,cr0
& && && && && & or& && &al,1
& && && && && & mov& &&&cr0,eax
& && && && && & ;清指令预取队列,并真正进入保护方式
& && && && && & JUMP16&&Code32_Sel,&OFFSET SPM32&
ToReal:& && && &;现在又回到实方式
& && && && && & mov& &&&ax,DSEG
& && && && && & mov& &&&ds,ax
& && && && && & mov& &&&sp,SaveSP
& && && && && & mov& &&&ss,SaveSS
& && && && && & DisableA20
& && && && && & sti
& && && && && & mov& &&&ax,4c00h
& && && && && & int& &&&21h
Start& && && &&&ENDP
;----------------------------------------------------------------------------
CSEG1& && && &&&ENDS& && && && && && && && && && &;代码段定义结束
;----------------------------------------------------------------------------
CSEG2& && && &&&SEGMENT USE32 'PM32'
& && && && && & ASSUME&&CS:CSEG2
;----------------------------------------------------------------------------
SPM32& && && &&&PROC
& && && && && & mov& &&&ax,Stacks_Sel
& && && && && & mov& &&&ss,ax
& && && && && & mov& &&&esp,StackLen
& && && && && & mov& &&&ax,DataS_Sel
& && && && && & mov& &&&ds,ax
& && && && && & mov& &&&ax,DataD_Sel
& && && && && & mov& &&&es,ax
& && && && && & xor& &&&esi,esi
& && && && && & xor& &&&edi,edi
& && && && && & mov& &&&ecx,DataLen
& && && && && & cld
Next:& && && &&&lodsb
& && && && && & push& & ax
& && && && && & CALL& & ToASCII
& && && && && & mov& &&&ah,7
& && && && && & shl& &&&eax,16
& && && && && & pop& &&&ax
& && && && && & shr& &&&al,4
& && && && && & CALL& & ToASCII
& && && && && & mov& &&&ah,7
& && && && && & stosd
& && && && && & mov& &&&al,20h
& && && && && & stosw
& && && && && & loop& & Next
& && && && && & JUMP32& &Code16_Sel,&OFFSET SPM16&
SPM32& && && &&&ENDP
;----------------------------------------------------------------------------
ToASCII& && && &PROC
& && && && && & and& &&&al,b
& && && && && & add& &&&al,30h
& && && && && & cmp& &&&al,39h
& && && && && & jbe& &&&Isdig
& && && && && & add& &&&al,7
IsDig:& && && & ret
ToASCII& && && &ENDP
;----------------------------------------------------------------------------
C32Len& && && & =& && & $
;----------------------------------------------------------------------------
CSEG2& && && &&&ENDS
;----------------------------------------------------------------------------
CSEG3& && && &&&SEGMENT USE16 'PM16'
& && && && && & ASSUME&&CS:CSEG3
;----------------------------------------------------------------------------
SPM16& && && &&&PROC
& && && && && & xor& &&&si,si
& && && && && & mov& &&&di,DataLen*3*2
& && && && && & mov& &&&ah,7
& && && && && & mov& &&&cx,DataLen
AGain:& && && & lodsb
& && && && && & stosw
& && && && && & loop& & AGain
& && && && && & mov& &&&ax,Normal_sel
& && && && && & mov& &&&ds,ax
& && && && && & mov& &&&es,ax
& && && && && & mov& &&&ss,ax
& && && && && & mov& &&&eax,cr0
& && && && && & and& &&&al,b
& && && && && & mov& &&&cr0,eax
& && && && && & jmp& &&&FAR PTR ToReal
SPM16& && && &&&ENDP
;----------------------------------------------------------------------------
CSEG3& && && &&&ENDS
;----------------------------------------------------------------------------
& && && && && & END& &&&Start
2.关于实现步骤的注释
(1)切换到保护模式的准备工作
建立全局描述符表,这里的全局描述符表含有两个16位数据段的描述符、一个16位代码段的描述符和一个16位的堆栈段描述符。此外,GDT中还有一个32位的代码段描述符,描述32位代码段,该描述符的属性字段中的D位为1。
(2)由实模式切换到保护模式
由实模式切换到保护模式32位代码段的方法与切换到16位代码段的方法相同。由保护模式16位代码段切换回实模式的方法与实例一相似。
在保护模式下,通过如下直接段间转移指令从32位代码段切换到16位代码段:
& & JUMP32& &Code16_Sel,&OFFSET SPM16&
从该宏指令的定义可知,该转移指令含48位指针,其高16位是16位代码段的选择子,低32位是16位代码段的入口偏移。该指令在32位方式下预取并执行。由于在32位方式下执行,所以要使用48位指针。
(3)显示指定内存区域的内容
在本实例中,采用直接写显示缓冲区的方法实现显示。假设显示缓冲区的开始物理地址是0B8000H, 3号文本显示模式,在屏幕的第一行进行显示。
3.特别说明
本实例在保护方式下使用了涉及堆栈操作的指令,因此建立了一个16位的保护模式下的堆栈段。
本实例仍作了大量的简化处理。如:没有建立IDT和LDT等,各特权级均是0。也没有采用分页管理机制。
从本实例的GDT中可见,两个数据段的界限都是根据实际大小而设置的。从源程序代码段CSEG3可见,在切换到实模式之前,把一个指向似乎没有用的数据段的描述符Normal的选择子装载到DS和ES。这是为什么呢?
内容 段寄存器 段基地址 段界限(固定) 段属性(固定)
存在性 特权级 已存取 粒度 扩展方向 可读性 可写性 可执行 堆栈大小 一致特权
CS 当前CS*16 0000FFFFH Y 0 Y B U Y Y Y - N
SS 当前SS*16 0000FFFFH Y 0 Y B U Y Y N W -
DS 当前DS*16 0000FFFFH Y 0 Y B U Y Y N - -
ES 当前ES*16 0000FFFFH Y 0 Y B U Y Y N - -
FS 当前FS*16 0000FFFFH Y 0 Y B U Y Y N - -
GS 当前GS*16 0000FFFFH Y 0 Y B U Y Y N - -
在分段管理机制一文中已介绍过,每个段寄存器都配有段描述符高速缓冲寄存器,这些高速缓冲寄存器在实方式下仍发挥作用,只是内容上与保护模式下有所不同。如上表所示,其中“Y”表示“是”; “N”表示“否”;“B”表示字节;“U”表示向上扩展,“W”表示以字方式操作堆栈。段基地址仍是 32位,其值是相应段寄存器值(段值)乘以16,在把段值装载到段寄存器时刷新。由于其值是16位段值乘上16,所以在实模式下基地址实际上有效位只有20位。每个段的32位段界限都固定为0FFFFH,段属性的许多位也是固定的。所谓固定是指在实方式下不可设置这些属性值,只能继续沿用保护方式下所设置的值。因此,在准备结束保护模式回到实模式之前,要通过加载一个合适的描述符选择子到有关段寄存器,以使得对应段描述符高速缓冲寄存器中含有合适的段界限和属性。本实例GDT中的描述符Normal就是这样一个描述符,在返回实模式之前把对应选择子Normal_Sel加载到DS和ES就是此目的。由于SS段描述符中的内容已符合实模式的需要,所以尽管也改变了SS,但不需要重新加载SS(本实例中重新加载了SS,这除了稍增加运行时间外,并没有什么坏处)。16位代码段描述符中的内容也符合实模式的需要,所以在通过16位代码段返回实模式时,CS段描述符中的内容也符合实模式的要求。需要注意的是,不能从32位代码段返回实模式,这是因为无法实现从32位代码段返回时CS高速缓冲寄存器中的属性符合实模式的要求(实模式不能改变段属性)。顺便说以下,实例一中的描述符都是符合实模式要求的。段描述符高速缓冲寄存器中含有合适的段界限
4.关于32位代码段程序设计的说明
在32位代码段中,缺省的操作数大小是32位,缺省的存储单元地址大小是32位。由于串操作指令使用的指针寄存器是ESI和EDI,LOOP指令使用的计数器是ECX,所以,在代码段CSEG2中,为了使用串操作指令,对ESI和EDI等寄存器赋初值。请比较代码段CSEG3中的相关片段和实例一中的相关片段,它们是16位代码段。}

我要回帖

更多关于 威纶宏指令 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信