能力值:
( LV2,RANK:10 )
|
-
-
11 楼
我在保护模式教程中就看到了这样的代码,JUMP16 CodeK_Sel,Virtual3这一行就是跳转到录virtual1子程序中的virtual3这行,下面是原代码
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
这是头文件:
;名称: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 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(重启动标志,为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
|