📄 asm4.asm
字号:
mov ah,4eh ;置显示属性(红底黄字)
EchoSub1: lodsb
or al,al
jz EchoSub2
stosw
jmp EchoSub1
EchoSub2: mov eax,[ebp+8] ;从堆栈中取调用程序的选择子
and al,3 ;调用程序的CPL在CS的RPL字段
add al,'0'
mov ah,4eh ;置显示属性(红底黄字)
stosw
pop ebp
retf
EchoSub ENDP
;----------------------------------------------------------------------------
EchoSubRLen = $
;----------------------------------------------------------------------------
EchoSubRSeg ENDS ;显示子程序代码段结束
;----------------------------------------------------------------------------
DemoCodeSeg SEGMENT PARA USE32 ;32位代码段(3级)
ASSUME CS:DemoCodeSeg
;----------------------------------------------------------------------------
DemoBegin PROC FAR
CALL32 ToEcho_Sel,0 ;显示当前特权级(变换到1级)
CALL32 ToT32B_Sel,0 ;转到过渡代码段(变换到0级)
DemoBegin ENDP
DemoCodeLen = $
;----------------------------------------------------------------------------
DemoCodeSeg ENDS ;32位代码段结束
;----------------------------------------------------------------------------
T32CodeSeg SEGMENT PARA USE32 ;32位过渡代码段(0级)
ASSUME CS:T32CodeSeg
;----------------------------------------------------------------------------
T32Begin PROC FAR
mov ax,DemoStack0_Sel ;建立0级堆栈
mov ss,ax
mov esp,DemoStack0Len
push DWORD PTR DemoStack3_Sel ;压入3级堆栈指针
push DemoStack3Len
push DWORD PTR DemoCode_SEL ;压入入口点
push OFFSET DemoBegin
retf ;利用RET实现转3级的演示代码
T32Begin ENDP
;----------------------------------------------------------------------------
T32End PROC FAR
JUMP32 TempCode_Sel,<OFFSET ToReal>
T32End ENDP
T32CodeLen = $
;----------------------------------------------------------------------------
T32CodeSeg ENDS
;----------------------------------------------------------------------------
TempCodeSeg SEGMENT PARA USE16 ;16位临时代码段(0级)
ASSUME CS:TempCodeSeg
;----------------------------------------------------------------------------
Virtual PROC FAR
mov ax,DemoTSS_Sel ;装载TR
ltr ax
mov ax,DemoLDT_Sel ;装载LDTR
lldt ax
JUMP16 ToT32A_Sel,0 ;通过调用门转过渡段
ToReal: mov ax,Normal_Sel ;准备切换回实模式
mov ds,ax
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>
Virtual ENDP
TempCodeLen = $
;----------------------------------------------------------------------------
TempCodeSeg 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,DS:RDataSeg
;----------------------------------------------------------------------------
Start PROC
mov ax,RDataSeg
mov ds,ax
cld
CALL InitGDT ;初始化全局描述符表GDT
mov ax,DemoLDTSeg
mov fs,ax
mov si,OFFSET DemoLDT
mov cx,DemoLDNum
CALL InitLDT ;初始化局部描述符表LDT
mov SSVar,ss
mov SPVar,sp
lgdt QWORD PTR VGDTR ;装载GDTR并切换到保护方式
cli
mov eax,cr0
or al,1
mov cr0,eax
JUMP16 <TempCode_Sel>,<OFFSET Virtual>
Real: mov ax,RDataSeg
mov ds,ax
lss sp,DWORD PTR SPVar ;又回到实方式
sti
mov ax,4c00h
int 21h
Start ENDP
;----------------------------------------------------------------------------
InitGDT PROC
push ds
mov ax,GDTSeg
mov ds,ax
mov cx,GDNum
mov si,OFFSET EFFGDT
InitG: mov ax,[si].BaseL
movzx eax,ax
shl eax,4
shld edx,eax,16
mov WORD PTR [si].BaseL,ax
mov BYTE PTR [si].BaseM,dl
mov BYTE PTR [si].BaseH,dh
add si,SIZE Desc
loop InitG
pop ds
mov bx,16
mov ax,GDTSeg
mul bx
mov WORD PTR VGDTR.Base,ax
mov WORD PTR VGDTR.Base+2,dx
ret
InitGDT ENDP
;----------------------------------------------------------------------------
;入口参数:FS:SI=第一个要初始化的描述符,CX=要初始化的描述符数
;----------------------------------------------------------------------------
InitLDT PROC
ILDT: mov ax,WORD PTR FS:[si].BaseL
movzx eax,ax
shl eax,4
shld edx,eax,16
mov WORD PTR fs:[si].BaseL,ax
mov BYTE PTR fs:[si].BaseM,dl
mov BYTE PTR fs:[si].BaseH,dh
add si,SIZE Desc
loop ILDT
ret
InitLDT ENDP
;----------------------------------------------------------------------------
RCodeSeg ENDS
END Start
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -