实模式保护模式区别
从80386开始,cpu有三种工作方式:实模式,保护模式和虚拟8086模式。只有在刚刚启动的时候是real-mode,等到linux操作系统运行起来以后就运行在保护模式。
实模式只能访问地址在1M以下的内存称为常规内存,我们把地址在1M 以上的内存称为扩展内存。
在保护模式下,全部32条地址线有效,可寻址高达4G字节的物理地址空间;
扩充的存储器分段管理机制和可选的存储器分页管理机制,不仅为存储器共享和保护提供了硬件支持,而且为实现虚拟存储器提供了硬件支持;
支持多任务,能够快速地进行任务切换和保护任务环境;
4个特权级和完善的特权检查机制,既能实现资源共享又能保证代码和数据的安全和保密及任务的隔离;
支持虚拟8086方式,便于执行8086程序。
1.虚拟8086模式是运行在保护模式中的实模式,为了在32位保护模式下执行纯16位程序。它不是一个真正的CPU模式,还属于保护模式。
2.保护模式同实模式的根本区别是进程内存受保护与否 。可寻址空间的区别只是这一原因的果。
实模式将整个物理内存看成分段的区域,程序代码和数据位于不同区域,系统程序和用户程序没有区别对待,而且每一个指针都是指向"实在"的物理地址。这样一来,用户程序的一个指针如果指向了系统程序区域或其他用户程序区域,并改变了值,那么对于这个被修改的系统程序或用户程序,其后果就很可能是灾难性的。为了克服这种低劣的内存管理方式,处理器厂商开发出保护模式。这样,物理内存地址不能直接被程序访问,程序内部的地址(虚拟地址)要由操作系统转化为物理地址去访问,程序对此一无所知。 至此,进程(这时我们可以称程序为进程了)有了严格的边界,任何其他进程根本没有办法访问不属于自己的物理内存区域,甚至在自己的虚拟地址范围内也不是可以任意访问的,因为有一些虚拟区域已经被放进一些公共系统运行库。这些区域也不能随便修改,若修改就会有: SIGSEGV(linux 段错误);非法内存访问对话框(windows 对话框)。
CPU启动环境为16位实模式,之后可以切换到保护模式。但从保护模式无法切换回实模式
3.事实上,现在的64位奔腾4处理器,拥有三种基本模式和一种扩展模式,
a)基本模式:
****保护模式:纯32位保护执行环境。
****实模式:纯16位无保护执行环境。
****系统管理模式:当SMI引脚为有效进入系统管理模式,首先保存当前的CPU上下文。它有独立的地址空间,用来执行电源管理或系统安全方面的指令。
b)扩展模式:****IA-32e模式,64位操作系统运行在该模式。该模式有两种子模式:
1)**兼容模式:该模式下,64位操作系统运行在32位兼容环境,能正常运行16,32位应用程序就像基本的保护模式一样,访问32位地址空间,但不能运行纯16位实模式程序(就是不能运行虚拟86模式程序了)。
2)**64位模式:在该模式下,处理器完全执行64位指令,使用64位地址空间和64操作数,运行16,32位程序必须切换到兼容模式。
IA-32e子模式的切换完全基于代码段寄存器。这样一来,运行在IA-32e模式中(64位)的OS完全可以无缝的运行所有16,32,64为应用程序,通过设置32位后的CS。
实模式保护模式切换方法
实例一的逻辑功能是,以十六进制数的形式显示从内存地址110000H开始的256个字节的值。本实例指定该内存区域的目的仅仅是想说明切
换到保护模式的必要性,因为在实模式下不能该指定内存区域,只有在保护模式下才能到该指定区域
本实例的具体实现步骤是:作切换到保护方式的准备;切换到保护方式;把指定内存区域的内容传送到位于常规内存的缓冲区中;切换回实模式;显示缓冲区内容。
1.包含文件
386保护模式汇编语言程序用到的包含文件如下所示,该包含文件在后面的程序中还要用到。
名称:386SCD.INC
功能:符号常量等的定义
IFNDEF __386SCD_INC
__386SCD_INC EQU 1
386P
打开A20地址线EnableA20 MACRO
push ax
in al,92h
or al,00000010b
out 92h,al
pop ax
ENDM
关闭A20地址线
DisableA20 MACRO
push ax
in al,92h
and al,11111101b
out 92h,al
pop ax
ENDM
16位偏移的段间直接转移指令的宏定义
JUMP16 MACRO Selector,Offset
DB 0eah ;操作码
DW Offset ;16位偏移量
DW Selector ;段值或段选择子
ENDM
32位偏移的段间直接转移指令的宏定义
COMMENT JUMP32
JUMP32 MACRO Selector,Offset
DB 0eah ;操作码
DD OFFSET
DW Selector ;段值或段选择子
ENDM
JUMP32
JUMP32 MACRO Selector,Offset
DB 0eah ;操作码
DW OFFSET
DW 0
DW Selector ;段值或段选择子
ENDM
16位偏移的段间调用指令的宏定义
CALL16 MACRO Selector,Offset
DB 9ah ;操作码
DW Offset ;16位偏移量
DW Selector ;段值或段选择子
ENDM
32位偏移的段间调用指令的宏定义
COMMENT CALL32
CALL32 MACRO Selector,Offset
DB 9ah ;操作码
DD Offset
DW Selector ;段值或段选择子
ENDM
CALL32
CALL32 MACRO Selector,Offset
DB 9ah ;操作码
DW Offset
DW 0
DW Selector ;段值或段选择子
ENDM
存储段描述符结构类型定义
Desc STRUC
LimitL DW 0 ;段界限
BaseL DW 0 ;段基地址
BaseM DB 0 ;段基地址
Attributes DB 0 ;段属性
LimitH DB 0 ;段界限
BaseH DB 0 ;段基地址
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 ;调试陷阱标志
TRIOMap DW $+2 ;指向I/O许可位图区的段内偏移
TSS ENDS
存储段描述符类型值说明
ATDR EQU 90h ;存在的只读段类型值
ATDW EQU 92h ;存在的可读写段属性值
ATDWA EQU 93h ;存在的已可读写段类型值
ATCE EQU 98h ;存在的只执行代码段属性值
ATCER EQU 9ah ;存在的可执行可读代码段属性值
ATCCO EQU 9ch ;存在的只执行一致代码段属性值
ATCCOR EQU 9eh ;存在的可执行可读一致代码段属性值
系统段描述符类型值说明
ATLDT EQU 82h ;局部描述符表段类型值
ATTaskGate EQU 85h ;任务门类型值
AT386TSS EQU 89h ;可用386任务状态段类型值
AT386CGate EQU 8ch ;386调用门类型值
AT386IGate EQU 8eh ;386中断门类型值
AT386TGate EQU 8fh ;386陷阱门类型值
DPL值说明
DPL0 EQU 00h ;DPL=0
DPL1 EQU 20h ;DPL=1
DPL2 EQU 40h ;DPL=2
DPL3 EQU 60h ;DPL=3
RPL值说明
RPL0 EQU 00h ;RPL=0
RPL1 EQU 01h ;RPL=1
RPL2 EQU 02h ;RPL=2
RPL3 EQU 03h ;RPL=3
IOPL值说明
IOPL0 EQU 0000h ;IOPL=0
IOPL1 EQU 1000h ;IOPL=1
IOPL2 EQU 2000h ;IOPL=2
IOPL3 EQU 3000h ;IOPL=3
其它常量值说明
D32 EQU 40h ;32位代码段标志
GL EQU 80h ;段界限以4K为单位标志
TIL EQU 04h ;TI=1
VMFL EQU 00020000h ;VMF=1
VMFLW EQU 0002h
IFL EQU 00000200h ;IF=1
RFL EQU 00010000h ;RF=1
RFLW EQU 0001h
NTL EQU 00004000h ;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属性位值,用户级
ENDIF
2.实例源程序
实例一的源程序如下所示:
名称:ASM1.ASM
;功能:演示实方式和保护方式切换
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 ;缓冲区
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,ax ;代码段开始偏移为0
mov BYTE PTR Code.BaseM,dl ;代码段界限已在定义时设置好
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,11111110b
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”,在此包含文件中定义了保护模式程序设计要用到的一些结构、宏及常量。下面对各实现步骤作些说明。
切换到保护方式的准备工作
在从实模式切换到保护模式之前,必须作必要的准备。准备工作的内容根据实际而定。最起码的准备工作是建立合适的全局描述符表,并使用GDTR指向该 GDT。因为在切换到保护方式时,至少要把代码段的选择子装载到CS,所以GDT中至少含有代码段的描述符。
从本实例源程序可见,全局描述符表GDT仅有四个描述符:第一个是空描述符;第二个是代码段描述符;第三个和第四个分别为源数据段及目标段描述符。本实例各描述符中的段界限是在定义时设置的,并且除伪描述符VGDTR中的界限按GDT的实际长度设置外,各使用的存储段描述符的界限都规定为0FFFFH。另外,描述符中的段属性也根据所描述段的类型被预置,各属性的定义在包含文件386SCD.INC中均有说明。从属性值可知,这三个段都是16位段。
由于在切换到保护方式后就要引用GDT,所以在切换到保护方式前必须装载GDTR。实例中使用如下指令装载GDTR:
LGDT QWORD PTR VGDTR
该指令的功能是把存储器中的伪描述符VGDTR装入到全局描述符表寄存器GDTR中。伪描述符VGDTR的结构如前所述结构类型PDESC所示,低字是以字节位单位的全局描述符表段的界限,高双字为描述符表段的线性基地址。本实例中未涉及到局部描述符表及中断描述符表,后面的文章将作详细说明。
由实模式切换到保护模式
在做好准备后,从实模式切换到保护模式并不难。原则上只要把控制寄存器CR0中的PE位置1即可。本实例采用如下三条指令设置PE位:
mov eax,cr0
or eax,1
mov cr0,eax
实际情况要比这复杂些。执行上面的三条指令后,处理器转入保护模式,但CS中的内容还是实模式下代码段的段值,而不是保护模式下代码段的选择子,所以在取指令之前得把代码段的选择子装入CS。为此,紧接着这三条指令,安排一条如下所示的段间转移指令:
JUMP16 Code_Sel , OFFSET Virtual
这条段间转移指令 在实模式下被预取并在保护方式下被执行 。利用这条段间转移指令可把保护模式下代码段的选择子装入CS,同时也刷新指令预取队列。从此真正进入保护模式。
由保护模式切换到实模式
在80386上,从保护模式切换到实模式的过程类似于从实模式切换到保护模式。原则上只要把控制寄存器CR0中的PE位清0即可。实际上,在此之后也要安排一条段间转移指令,一方面清指令预取队列,另一方面把实模式下代码段的段值送CS。 这条段间转移指令在保护方式下被预取并在实模式下被执行 。
保护模式下的传送
首先,把源数据段和目标段的选择子装入DS和ES寄存器,这两个描述符已在实模式下设置好,把选择子装入段寄存器就意味着把包括基地址在内的段信息装入到了段描述符高速缓冲寄存器。然后设置指针寄存器SI和DI的初值,也设置计数器CX的初值。根据预置的段属性,在保护方式下,代码段也仅是16位段,串操作指令只使用16位的SI、DI和CX等寄存器。最后利用串操作指令实施传送。
显示缓冲区中的内容
由于缓冲区在常规内存中,所以在实模式下根据要求按十六进制显示其内容是很容易理解的,这里就不再多说。
4.内存映象
在源程序中没有把GDT作为一个单独的段对待,但在进入保护方式后,它是一个独立的段。从对代码段和源数据段描述符所赋的基地址和段界限值可见,代码段和数据段有部分覆盖。尽管这样做不利于代码和的安全,但如果需要,这样做是可行的。本实例运行时的内存映象如下图所示。
5.特别说明
作为第一个实模式和保护模式切换的例子,本实例作了大量的简化处理。
通常,由实模式切换到保护模式的准备工作还应包含建立中断描述符表。但本实例没有建立中断描述符表。为此,要求整个过程在关中断的情况下进行;要求不使用软中断指令;假设不发生任何异常。否则会导致系统崩溃。
本实例未使用局部描述符表,所以在进入保护模式后没有设置局部描述符表寄存器LDTR。为此,在保护模式下使用的段选择子都指定GDT中的描述符。
本实例未定义保护模式下的堆栈段,GDT中没有堆栈段描述符,在保护模式下没有设置SS,所以在保护方式下没有涉及堆栈操作的指令。
本实例各描述符特权级DPL和各选择子的请求特权级RPL均为0,在保护方式下运行时的当前特权级CPL也是0。
本实例没有采用分页管理机制,也即CR0中的PG位为0,线性地址就是存储单元的物理地址。
6.打开和关闭地址线A20
PC及其兼容机的第21根地址线较特殊,计算机系统中一般安排一个 “门”控制该地址线是否有效。为了地址在1M以上的存储单元,应先打开控制地址线A20的“门”。这种设置与实模式下只使用最低端的1M字节存储空间有关,与处理器是否工作在实模式或保护方式无关,即使在关闭地址线A20时,也可进入保护模式。
如何打开和关闭地址线A20与计算机系统的具体设置有关。在本文中介绍的包含文件386SCD.INC中定义了两个宏,打开地址线A20的宏 EnableA20和关闭地址线A20的宏DisableA20,此两个宏指令在一般的PC兼容机上都是可行的。
二演示32位代码段和16位代码段切换的实例
实例二的逻辑功能是,以十六进制数和ASCII字符两种形式显示从内存地址100000H开始的16个字节的内容。
从功能上看,本实例类似于实例一,但在实现方法上却有了改变,它更能反映出实模式和保护模式切换的情况。具体实现步骤是:作切换到保护方式的准备;切换到保护方式的一个32位代码段;把指定内存区域的内容以字节为单位,转换成对应的十六进制数的ASCII码,并直接填入显示缓冲区实现显示;再变换到保护方式下的一个16位代码段;把指定内存区域的内容直接作为ASCII码填入显示缓冲区中实现显示;切换回实模式。
1.实例二源程序
实例二的源程序如下所示:
名称:ASM2.ASM
功能:演示实方式和保护方式切换
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 3999,8000h,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 ;堆栈段描述符选择子
DtaLen = 16
DSEG ENDS ;段定义结束
StackSeg SEGMENT PARA STACK USE16
StackLen = 256
DB StackLen DUP
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,00001111b
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,11111110b
mov cr0,eax
jmp FAR PTR ToReal
SPM16 ENDP
CSEG3 ENDS
END Start
2.关于实现步骤的注释
切换到保护模式的准备工作
建立全局描述符表,这里的全局描述符表含有两个16位段的描述符、一个16位代码段的描述符和一个16位的堆栈段描述符。此外,GDT中还有一个32位的代码段描述符,描述32位代码段,该描述符的属性字段中的D位为1。
由实模式切换到保护模式
由实模式切换到保护模式32位代码段的方法与切换到16位代码段的方法相同。由保护模式16位代码段切换回实模式的方法与实例一相似。
在保护模式下,通过如下直接段间转移指令从32位代码段切换到16位代码段:
JUMP32 Code16_Sel , OFFSET SPM16
从该宏指令的定义可知,该转移指令含48位指针,其高16位是16位代码段的选择子,低32位是16位代码段的入口偏移。 该指令在32位方式下预取并执行 。由于在32位方式下执行,所以要使用48位指针。
显示指定内存区域的内容
在本实例中,采用直接写显示缓冲区的方法实现显示。假设显示缓冲区的开始物理地址是0B8000H, 3号文本显示模式,在屏幕的第一行进行显示。
3.特别说明
本实例在保护方式下使用了涉及堆栈操作的指令,因此建立了一个16位的保护模式下的堆栈段。
本实例仍作了大量的简化处理。如:没有建立IDT和LDT等,各特权级均是0。也没有采用分页管理机制。