;名称: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 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字节为单位的缓冲区长度 repz movsd ;传送 ;切换回实模式 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
|