⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 asm3.asm

📁 保护模式教程源码 The source code of protection mode in dos
💻 ASM
字号:
;名称:ASM3.ASM
;功能:演示任务内无特权级变换的转移
;编译:TASM ASM3.ASM
;连接:TLINK ASM3.OBJ
;----------------------------------------------------------------------------
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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -