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

📄 386p6a.asm

📁 汇编学习经典,DOS环境可在 win2000下使用
💻 ASM
字号:
;**********************************************************************
;   保护方式下的编程示例 			陈家祺	1996.6
;       ---全局描述符的应用方法	
;
;   1 实方式进入保护方式及保护方式返回实方式方法
;   2 保护方式下的指令操作(直接写屏,满屏显示'A')
;   * 环境: MASM6.0,DOS6.2,DOS7.0, 80486主机, Himem.sys, 
;	    不能装栽Emm386.exe,因为Emm386.exe装载后,cpu处于虚拟8086方式下
;**********************************************************************
.MODEL small
.386p
jumpfar	MACRO	_sel,_offset	; 保护方式跳转指令
	db 0eah			; 功能与目的:
	dw _offset		; 1. 清除指令队列
	dw _sel			; 2. 选择字sel -> CS
	ENDM

set_ba	MACRO	_seg,_gdt_seg	; 设置_gdt_seg段描述符的基地址
	mov ax,_seg		; 将实方式DOS的段地址_seg换算为24位线性基地址
	mov cx,10h		
	mul cx			; dl.ax = _seg*16
	mov di,offset _gdt_seg	; di = _gdt_seg描述符的偏移地址
	mov [di].base_15_0,ax	; 存入GDT描述符中
	mov [di].base_23_16 ,dl
	ENDM

mov_s	MACRO	_seg,_sel	; 设置段寄存器
	mov ax,_sel		
	mov _seg,ax		
	ENDM

desc 	struc			; GDT全局描述符的结构
  limit_15_0    dw ?		; 界限15-0
  base_15_0   	dw ?		; 基地址15-0
  base_23_16   	db ?		; 基地址23-16
  access   	db ?		; 访问权
  gran     	db ?		; 粒度,类型,界限19-16
  base_31_24   	db ?		; 基地址31-24
desc 	ends
.DATA				; 数据段
char		db   'A'	; 要显示的字符

;	*****	GDT 描述符表	*****
gdt_def		LABEL	BYTE
		desc < >		;必须为空描述符
gdt_cs		desc <_end+100h, ?, ? ,9ah,00h,00h>	;00000 - 001D9H ( )
gdt_ds		desc < 000fh,  ?  , ? ,92h,00h,00h> 	;00000 - 0000fH (16b)
gdt_ss		desc < 0000h,  ?  , ? ,96h,40h,00h>
gdt_uds		desc <00fffh,8000h,0bh,92h,00h,00h>	;00000 - 00fffH ( 4Kb)
gdt_cs_r	desc <0ffffh,  ?  , ? ,9ah,00h,00h>	;00000 - 0ffffH (64Kb)
gdt_r		desc <0ffffh,  ?  , ? ,92h,00h,00h>	;00000 - 0ffffH (64Kb)
gdt_end		LABEL	BYTE
					; 设置GDTR用
gdtsize		dw gdt_end-gdt_def	; GDT描述符表的长度
gdtaddr		dd ?			; GDT描述符表的线性基地址31-0

gdt_cs_sel 	equ 08h			; CS选择字
gdt_ds_sel 	equ 10h			; DS选择字
gdt_ss_sel 	equ 18h			; SS选择字
gdt_uds_sel 	equ 20h			; 用户DS选择字
gdt_cs_r_sel 	equ 28h			; CS选择字   (具有实方式的界限与属性)
gdt_r_sel 	equ 30h			; DS/SS选择字(具有实方式的界限与属性)

.STACK					; 堆栈段, 堆栈空间为1024
.CODE   				; 代码段
	.STARTUP			; 初始化DS,SS和SP
	cli
	call prot			; 调用保护方式操作子程
	sti
	mov	ah,0
	int	16h			; BIOS键盘中断调用,等待按键!
	.EXIT 0				; 返回DOS!

prot 	proc near
	set_ba cs, gdt_cs		; 设置CS描述符的基地址
	set_ba ds, gdt_ds		; 设置DS描述符的基地址
	set_ba ss, gdt_ss		; 设置SS描述符的基地址
	set_ba cs, gdt_cs_r		; 设置CS_r描述符的基地址

	mov eax,ds			; 计算GDT描述符表的线性基地址31-0
	shl eax,4			
	add eax,offset gdt_def
	mov gdtaddr,eax

	LGDT fword ptr gdtsize		; 装载GDT给GDTR寄存器

	mov eax,cr0			
	or  al,1			; 设置控制寄存器CR0的PE位
	mov cr0,eax			; 进入保护方式
	jumpfar	gdt_cs_sel,prot_user	; 清除指令队列,
prot_user:				; CS=gdt_cs_sel(保护方式码段)
	mov_s ss,gdt_ss_sel		; 设置保护方式的堆栈段

	call vram_disp			; 调用保护方式下显示子程

	jumpfar	gdt_cs_r_sel,next	; CS=gdt_cs_r_sel
next:					; 设置具有实方式代码段的界限与属性
	mov_s ds,gdt_r_sel		; 设置实方式数据段的界限与属性
	mov_s ss,gdt_r_sel		; 设置实方式堆栈段的界限与属性
	mov eax,cr0			
	and al,0feh			; 清除控制寄存器CR0的PE位
	mov cr0,eax			; 切换到实方式
	jmp far	ptr real_mode		; 清除指令队列,CS=_TEXT(实方式码段) 
real_mode:				
	mov_s ds,DGROUP			; 恢复DOS数据段的段地址		
	mov_s ss,DGROUP			; 恢复DOS堆栈段的段地址		
	ret
prot  endp

vram_disp proc near			; 保护方式下直接写屏子程
	pushad
	mov_s ds,gdt_ds_sel		; 设置保护方式的堆栈段
	mov dl,char			; 显示字符'A'
	mov_s ds,gdt_uds_sel		; 设置保护方式的堆栈段
	mov cx,80*25			; 满屏字符数.
	mov ebx,00000000h
	mov ah,17h			; 字符颜色属性,蓝底白字
	mov al,dl			; 显示字符'A'
l1:	mov [ebx],ax
	add ebx,2
	loop l1
	popad
	ret
vram_disp endp	
_end	LABEL	BYTE
   	END 

⌨️ 快捷键说明

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