忆杰的博客

忆杰的博客

保护模式1:由实模式切换到保护模式实例

简单的由实模式切换到保护模式的例子, 在MASM9下面写的, 运行的时候必须在Dos下面运行.
 

   保护模式确实是比较复杂啊, 对这个保护模式的复杂度又有了更深刻的理解, 当然这个例子代码不是很长, 只出生后了GDT, 然后在保护模式下写了个字符串而已.. 但是确实是进入了保护模式!
   这个保护模式的复杂, 我觉得一个由于本来保护模式就比较抽象难以理解, 吓到了不少的人, 在一个现在确实很少这方面的资料啊, 能够找到的资料大部分代码都是比较比较陈旧的, 比如用TASM写, 说实话. 这个东西我是从没有倒腾过. 好在语法和MASM差别不是很大, 万幸..
   一步一步的摸索, 遇到很多问题,. 当然也得到了唐老师的悉心指点,和童哥的热心帮助..  灰常给力..
   源码是Masm9下面写的, 也就是VS2008里面Copy出来那个版本了, 谁说写Dos下的程序只能用masm5呢?? 又好东西干嘛不用.. 你可以在这里下载源码的, 只要你电脑上设置好MASM的环境变量, 里面的makefile直接编译就可以的.. 又问题可以发个Email:JoenChen@foxmail.com

        http://www.joenchen.com/JoenTools/Protect1.rar

 

;============================================================================
	;简单的切换到保护模式实例
	;MASM9.00  + link 5.60  TAB = 8
	;编译: 	ml /c /omf pm.asm
	;链接:	link pm.obj;
;============================================================================
	.686p
	Include pm.inc				;保护模式的结构定义

DataSeg	Segment	use16
GDT	label	byte				;全局描述符表
Dummy:		Descriptor	0, 0, 0		;空的描述符
;============================================================================
;				;段基址	  	;段界限		;属性
CodeDesc:	Descriptor 	0,		0ffffh, 	DA_C	;非一致代码段16位
VideoDesc:	Descriptor	0b8000h,	0ffffh, 	DA_DRW	;显存段(可读写)

GDT_Len		equ	$-GDT			;GDT长度

GDT_Ptr		word	GDT_Len -1		;GDTR伪描述符
		dword	0

SelectorCode	equ	CodeDesc - GDT		;代码段选择子偏移
SelectorVideo	equ	VideoDesc - GDT		;视频段选择子偏移
;============================================================================

DataSeg	Ends
;============================================================================
	;程序入口段, 初始化GDTR 和一个代码段描述符, 然后跳到保护模式
;============================================================================
CodeSeg	Segment	use16				;16位代码段
Jmain	Proc

	xor	eax, eax
	mov	ax, DataSeg
	mov	ds, ax
;----------------------------------------------------------------------------
	;初始化	CodeDesc描述符的基址
	xor	eax, eax
	mov	ax, cs
	shl	eax, 4
	mov	word ptr ds:[CodeDesc+2], ax	;段基址低地址
	shr	eax, 16
	mov	byte ptr ds:[CodeDesc+4], al	;段基址高地址低位
	mov	byte ptr ds:[CodeDesc+7], ah	;段基址高地址高位

;----------------------------------------------------------------------------
	;初始化并加载GDTR伪描述符
	xor	eax, eax
	mov	ax, ds
	shl	eax, 4				;GTDR伪描述符的段地址
	add	eax, offset GDT
	mov	dword ptr ds:[GDT_Ptr+2], eax	;GTDR伪描述符基址

	lgdt	fword ptr ds:[GDT_Ptr]
;----------------------------------------------------------------------------
	cli
	_EnableA20				;打开A20地址线

	mov	eax, cr0
	or	eax, 1
	mov	cr0, eax			;开启Cr0的分段标记正式进入保护模式

	;这行代码有着特殊的意义, 由此进入保护模式
	Jmp16	SelectorCode,  <offset _Protect >
;----------------------------------------------------------------------------
	;现在已经进入了保护模式(进入历史性的时刻)
;----------------------------------------------------------------------------
	;进入保护模式就写一个字符就可以
_Protect:
	mov	ax, SelectorVideo
	mov	es, ax
	mov	edi, (80*11+40) * 2		;屏幕的第11行第40列
	mov	ah, 0ch				;属性
	mov	al, 'J'				;字符
	mov	word ptr es:[edi], ax		;写入一个字符串 Joen
	add	edi,2
	mov	al, 'o'
	mov	word ptr es:[edi], ax
	add	edi,2
	mov	al, 'e'
	mov	word ptr es:[edi], ax
	add	edi,2
	mov	al, 'n'
	mov	word ptr es:[edi], ax

	mov	eax, cr0
	and	al, 0feh			;关闭PE分段位, 进入实模式
	mov	cr0, eax

	Jmp16	<SEG _Real>, < offset _Real >	;又跳回实模式
;----------------------------------------------------------------------------
	;又跳回实模式了
;----------------------------------------------------------------------------
_Real:	mov	ax, cs
	mov	ds, ax
	mov	es, ax
	mov	ss, ax
	_DisableA20				;关闭A20地址线
	sti
	mov	ax, 4c00h
	int	21h				;退出程序
Jmain 	Endp
CodeSeg	Ends
;----------------------------------------------------------------------------
End	Jmain

发表评论


Warning: Undefined variable $user_ID in /www/wwwroot/joenchen.com/wp-content/themes/agan/comments.php on line 66

您必须登录 才能进行评论。