现在的位置: 首页 > 综合 > 正文

跟踪了解80X86实模式和保护模式转换的技术细节

2013年09月22日 ⁄ 综合 ⁄ 共 11791字 ⁄ 字号 评论关闭

 

一.编写实方式和保护方式切换演示程序

;编译要点 通过masm/link 生成exe文件,再用exe2bin转成.com文件

;演示实方式和保护方式切换
;----------------------------------------------------------------------------
INCLUDE         386SCD.INC

;----------------------------------------------------------------------------
CSEG            SEGMENT USE16                   ;16
位代码段
                ASSUME  CS:CSEG,DS:CSEG
org 08c00h      ;
为了便于通过bochs调试,写成COM,偏移为08c00h
                ;(
参见: 如何在windows下利用BOCHS调试80x86汇编程序
)
Start:
                jmp Begin
;----------------------------------------------------------------------------
GDT             LABEL   BYTE                    ;
全局描述符表

DUMMY           Desc    <>                      ;
空描述符
Code            Desc    <0ffffh,,,ATCE,,>       ;
代码段描述符
DataD           Desc    <8000,8000h,0bh,ATDW,,> ;
目标数据段描述符
Normal          Desc    <0ffffh,,,ATDW,,>       ;
规范段描述符
;----------------------------------------------------------------------------
GDTLen          =       $-GDT                   ;
全局描述符表长度
VGDTR           PDesc   <GDTLen-1,>             ;
伪描述符
;----------------------------------------------------------------------------
Code_Sel        =       Code-GDT                ;
代码段选择子
DataD_Sel       =       DataD-GDT               ;
目标数据段选择子
Normal_Sel      =       Normal-GDT              ;
规范段选择子
;----------------------------------------------------------------------------
DataLen         =       960                     ;
缓冲区字节长度
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
Begin:
                mov     ax,CSEG
                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
                ;
加载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,DataD_Sel
                mov     es,ax                   ;
加载显示缓冲区描述符
                cld
                mov     di,320                  ;
设置指针初值
                mov     cx,DataLen              ;
设置数据长度
                mov     ax,7b1h
                repz    stosw
                mov     ax,Normal_Sel
                mov     es,ax
                ;
切换回实模式
                mov     eax,cr0
                and     al,11111110b
                mov     cr0,eax
                ;
清指令预取队列,进入实方式
                JUMP16  <SEG Real>,<OFFSET Real>
Real:           ;
现在又回到实方式
                DisableA20
                sti
                jmp $
;Start           ENDP
;----------------------------------------------------------------------------
CSEG            ENDS                            ;
代码段定义结束
;----------------------------------------------------------------------------
                END     Start

 

 

 

 

 

 

 

 

 

386SCD.INC

;名称: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
位偏移的段间直接转移指令的宏定义(16位代码段中使用)
;----------------------------------------------------------------------------
JUMP16          MACRO   Selector,Offset
                DB      0eah     ;
操作码

                DW      Offset   ;16
位偏移量
                DW      Selector ;
段值或段选择子
                ENDM
;----------------------------------------------------------------------------
;32
位偏移的段间直接转移指令的宏定义(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
位偏移的段间调用指令的宏定义(16位代码段中使用)
;----------------------------------------------------------------------------
CALL16          MACRO   Selector,Offset
                DB      9ah      ;
操作码

                DW      Offset   ;16
位偏移量
                DW      Selector ;
段值或段选择子
                ENDM
;----------------------------------------------------------------------------
;32
位偏移的段间调用指令的宏定义(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 ;
段界限(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            =       90h ;
存在的只读数据段类型值
ATDW            =       92h ;
存在的可读写数据段属性值
ATDWA           =       93h ;
存在的已访问可读写数据段类型值
ATCE            =       98h ;
存在的只执行代码段属性值
ATCER           =       9ah ;
存在的可执行可读代码段属性值
ATCCO           =       9ch ;
存在的只执行一致代码段属性值
ATCCOR          =       9eh ;
存在的可执行可读一致代码段属性值
;----------------------------------------------------------------------------
;
系统段描述符类型值说明
;----------------------------------------------------------------------------
ATLDT           =       82h ;
局部描述符表段类型值
ATTaskGate      =       85h ;
任务门类型值
AT386TSS        =       89h ;
可用386任务状态段类型值
AT386CGate      =       8ch ;386
调用门类型值
AT386IGate      =       8eh ;386
中断门类型值
AT386TGate      =       8fh ;386
陷阱门类型值
;----------------------------------------------------------------------------
;DPL
值说明
;----------------------------------------------------------------------------
DPL0            =       00h ;DPL=0
DPL1            =       20h ;DPL=1
DPL2            =       40h ;DPL=2
DPL3            =       60h ;DPL=3
;----------------------------------------------------------------------------
;RPL
值说明
;----------------------------------------------------------------------------
RPL0            =       00h ;RPL=0
RPL1            =       01h ;RPL=1
RPL2            =       02h ;RPL=2
RPL3            =       03h ;RPL=3
;----------------------------------------------------------------------------
;IOPL
值说明
;----------------------------------------------------------------------------
IOPL0           =       0000h ;IOPL=0
IOPL1           =       1000h ;IOPL=1
IOPL2           =       2000h ;IOPL=2
IOPL3           =       3000h ;IOPL=3
;----------------------------------------------------------------------------
;
其它常量值说明
;----------------------------------------------------------------------------
D32             =       40h       ;32
位代码段标志
GL              =       80h       ;
段界限以4K为单位标志
TIL             =       04h       ;TI=1(
局部描述符表标志)
VMFL            =       00020000h ;VMF=1
VMFLW           =       0002h
IFL             =       00000200h ;IF=1
RFL             =       00010000h ;RF=1(
重启动标志,1表示忽略调试故障
)
RFLW            =       0001h
NTL             =       00004000h ;NT=1
;----------------------------------------------------------------------------
;
分页机制使用的常量说明

;----------------------------------------------------------------------------
PL              =       1     ;
页存在属性位
RWR             =       0     ;R/W
属性位值,/执行
RWW             =       2     ;R/W
属性位值,//执行
USS             =       0     ;U/S
属性位值,系统级
USU             =       4     ;U/S
属性位值,用户级
;----------------------------------------------------------------------------
;ENDIF

抱歉!评论已关闭.