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

📄 asm1.asm

📁 用纯C写的基于x86结构的保护模式相关操作
💻 ASM
字号:
;名称:ASM1.ASM
;功能:演示实方式和保护方式切换(切换到16位代码段)
;----------------------------------------------------------------------------
INCLUDE         386SCD.INC
;----------------------------------------------------------------------------
;字符显示宏指令的定义
;----------------------------------------------------------------------------
EchoCh          MACRO   ascii
                mov     ah,2
                mov     dl,ascii
                int     21h
                ENDM
;----------------------------------------------------------------------------
DSEG            SEGMENT USE16                 ;16位数据段
;----------------------------------------------------------------------------
GDT             LABEL   BYTE                  ;全局描述符表
DUMMY           Desc    <>                    ;空描述符
Code            Desc    <0ffffh,,,ATCE,,>     ;代码段描述符
DataS           Desc    <0ffffh,0,11h,ATDW,,> ;源数据段描述符
DataD           Desc    <0ffffh,,,ATDW,,>     ;目标数据段描述符
;----------------------------------------------------------------------------
GDTLen          =       $-GDT                 ;全局描述符表长度
VGDTR           PDesc   <GDTLen-1,>           ;伪描述符
;----------------------------------------------------------------------------
Code_Sel        =       Code-GDT              ;代码段选择子
DataS_Sel       =       Datas-GDT             ;源数据段选择子
DataD_Sel       =       DataD-GDT             ;目标数据段选择子
;----------------------------------------------------------------------------
BufLen          =       256                   ;缓冲区字节长度
Buffer          DB      BufLen DUP(0)         ;缓冲区
;----------------------------------------------------------------------------
DSEG            ENDS                          ;数据段定义结束
;----------------------------------------------------------------------------
CSEG            SEGMENT USE16                 ;16位代码段
                ASSUME  CS:CSEG,DS:DSEG
;----------------------------------------------------------------------------
Start           PROC
                mov     ax,DSEG
                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
                ;设置目标数据段描述符
                mov     ax,ds
                mul     bx                     ;计算并设置目标数据段基址
                add     ax,OFFSET Buffer
                adc     dx,0
                mov     WORD PTR DataD.BaseL,ax
                mov     BYTE PTR DataD.BaseM,dl
                mov     BYTE PTR DataD.BaseH,dh
                ;加载GDTR
                lgdt    FWORD PTR VGDTR    ;这一句改过,原版是lgdt    QWORD PTR VGDTR
                cli                            ;关中断
                EnableA20                      ;打开地址线A20
                ;切换到保护方式
                mov     eax,cr0
                or      eax,1
		mov	cr0,eax
                ;清指令预取队列,并真正进入保护方式
                JUMP16  Code_Sel,<OFFSET Virtual>
Virtual:        ;现在开始在保护方式下运行
                mov     ax,DataS_Sel
                mov     ds,ax                  ;加载源数据段描述符
                mov     ax,DataD_Sel
                mov     es,ax                  ;加载目标数据段描述符
                cld
                xor     si,si
                xor     di,di                  ;设置指针初值
                mov     cx,BufLen/4            ;设置4字节为单位的缓冲区长度
rrr:            movsd                          ;从这句开始到loop rrr 语句都是改过的
                inc     si                        ;原句是一句 repz    movsd                     
                inc     di                        ;经检查movsd指令不能带repz前缀
                loop    rrr
                ;切换回实模式
                mov     eax,cr0
                and     al,11111110b
                mov     cr0,eax
                ;清指令预取队列,进入实方式
                JUMP16  <SEG Real>,<OFFSET Real>
Real:           ;现在又回到实方式
                DisableA20
                sti
                mov     ax,DSEG
                mov     ds,ax
                mov     si,OFFSET Buffer
                cld
                mov     bp,BufLen/16
NextLine:       mov     cx,16
NextCh:         lodsb
                push    ax
                shr     al,1
                call    ToASCII
                EchoCh  al
                pop     ax
                call    ToASCII
                EchoCh  al
                EchoCh  ' '
                loop    NextCh
                EchoCh  0dh
                EchoCh  0ah
                dec     bp
                jnz     NextLine
                mov     ax,4c00h
                int     21h
Start           ENDP
;----------------------------------------------------------------------------
ToASCII         PROC
                and     al,0fh
                add     al,90h
                daa
                adc     al,40h
                daa
                ret
ToASCII         ENDP
;----------------------------------------------------------------------------
CSEG            ENDS                           ;代码段定义结束
;----------------------------------------------------------------------------
                END     Start

⌨️ 快捷键说明

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