一.编写实方式和保护方式切换演示程序 ;编译要点: 通过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
;伪描述符 ;---------------------------------------------------------------------------- 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,
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
,
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 MACRO Selector,Offset DB 0eah ;操作码 DD OFFSET DW Selector ;段值或段选择子 ENDM
;------------------------------------------------- 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 MACRO Selector,Offset DB 9ah ;操作码 DD Offset DW Selector ;段值或段选择子 ENDM
;------------------------------------------------- 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 本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/b2b160/archive/2009/03/04/3957386.aspx
跟踪了解80X86实模式和保护模式转换的技术细节
最新推荐文章于 2020-10-29 19:18:37 发布