;名称:ASM2.ASM ;功能:演示实方式和保护方式切换(切换到32位代码段) ;---------------------------------------------------------------------------- INCLUDE 386SCD.INC ;---------------------------------------------------------------------------- DSEG SEGMENT USE16 ;16位数据段 ;---------------------------------------------------------------------------- GDT LABEL BYTE ;全局描述符表 DUMMY Desc <> ;空描述符 Normal Desc <0ffffh,,,ATDW,,> ;规范段描述符 Code32 Desc <C32Len-1,,,ATCE,D32,> ;32位代码段描述符 Code16 Desc <0ffffh,,,ATCE,,> ;16位代码段描述符 DataS Desc <DataLen-1,0,10h,ATDR,,> ;源数据段描述符 DataD Desc <3999,8000h,0bh,ATDW,,> ;显示缓冲区描述符 Stacks Desc <StackLen-1,,,ATDW,,> ;堆栈段描述符 ;---------------------------------------------------------------------------- GDTLen = $-GDT ;全局描述符表长度 VGDTR PDesc <GDTLen-1,> ;伪描述符 ;---------------------------------------------------------------------------- SaveSP DW ? ;用于保存SP寄存器 SaveSS DW ? ;用于保存SS寄存器 ;---------------------------------------------------------------------------- Normal_Sel = Normal-GDT ;规范段描述符选择子 Code32_Sel = Code32-GDT ;32位代码段选择子 Code16_Sel = Code16-GDT ;16位代码段选择子 DataS_Sel = Datas-GDT ;源数据段选择子 DataD_Sel = DataD-GDT ;目标数据段选择子 Stacks_Sel = Stacks-GDT ;堆栈段描述符选择子 ;---------------------------------------------------------------------------- DataLen = 16 ;---------------------------------------------------------------------------- DSEG ENDS ;数据段定义结束 ;---------------------------------------------------------------------------- StackSeg SEGMENT PARA STACK USE16 StackLen = 256 DB StackLen DUP(0) StackSeg ENDS ;---------------------------------------------------------------------------- CSEG1 SEGMENT USE16 'REAL' ;16位代码段 ASSUME CS:CSEG1,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 ;设置32位代码段描述符 mov ax,CSEG2 mul bx mov WORD PTR Code32.BaseL,ax mov BYTE PTR Code32.BaseM,dl mov BYTE PTR Code32.BaseH,dh ;设置16位代码段描述符 mov ax,CSEG3 mul bx mov WORD PTR Code16.BaseL,ax ;代码段开始偏移为0 mov BYTE PTR Code16.BaseM,dl ;代码段界限已在定义时设置好 mov BYTE PTR Code16.BaseH,dh ;设置堆栈段描述符 mov ax,ss mov WORD PTR SaveSS,ax mov WORD PTR SaveSP,sp mov ax,StackSeg mul bx mov WORD PTR Stacks.BaseL,ax mov BYTE PTR Stacks.BaseM,dl mov BYTE PTR Stacks.BaseH,dh ;加载GDTR lgdt QWORD PTR VGDTR cli ;关中断 EnableA20 ;打开地址线A20 ;切换到保护方式 mov eax,cr0 or al,1 mov cr0,eax ;清指令预取队列,并真正进入保护方式 JUMP16 Code32_Sel,<OFFSET SPM32> ToReal: ;现在又回到实方式 mov ax,DSEG mov ds,ax mov sp,SaveSP mov ss,SaveSS DisableA20 sti mov ax,4c00h int 21h Start ENDP ;---------------------------------------------------------------------------- CSEG1 ENDS ;代码段定义结束 ;---------------------------------------------------------------------------- CSEG2 SEGMENT USE32 'PM32' ASSUME CS:CSEG2 ;---------------------------------------------------------------------------- SPM32 PROC mov ax,Stacks_Sel mov ss,ax mov esp,StackLen mov ax,DataS_Sel mov ds,ax mov ax,DataD_Sel mov es,ax xor esi,esi xor edi,edi mov ecx,DataLen cld Next: lodsb push ax CALL ToASCII mov ah,7 shl eax,16 pop ax shr al,4 CALL ToASCII mov ah,7 stosd mov al,20h stosw loop Next JUMP32 Code16_Sel,<OFFSET SPM16> SPM32 ENDP ;---------------------------------------------------------------------------- ToASCII PROC and al,00001111b add al,30h cmp al,39h jbe Isdig add al,7 IsDig: ret ToASCII ENDP ;---------------------------------------------------------------------------- C32Len = $ ;---------------------------------------------------------------------------- CSEG2 ENDS ;---------------------------------------------------------------------------- CSEG3 SEGMENT USE16 'PM16' ASSUME CS:CSEG3 ;---------------------------------------------------------------------------- SPM16 PROC xor si,si mov di,DataLen*3*2 mov ah,7 mov cx,DataLen AGain: lodsb stosw loop AGain mov ax,Normal_sel mov ds,ax mov es,ax mov ss,ax mov eax,cr0 and al,11111110b mov cr0,eax jmp FAR PTR ToReal SPM16 ENDP ;---------------------------------------------------------------------------- CSEG3 ENDS ;---------------------------------------------------------------------------- END Start
|