操作系统开发系列—3.保护模式的优势

在上一篇中我们虽然成功进入了保护模式,但是并没有体验到保护模式带给我们的便利。其实在保护模式下寻址空间可以达到4GB,实模式下1MB的寻址能力差得太远了。那么下面,我们就把程序稍作修改,体验一下它对超过1MB内存的访问能力。

我们来试验一下读写大地址内存。在前面程序的基础上,新建一个段,这个段以5MB为基址,远远超出实模式下1MB的界限。我们先读出开始处8字节的内容,然后写入一个字符串,再从中读出8字节,如下所示:

	call	TestRead
	call	TestWrite
	call	TestRead

如果读写成功的话,两次读出的内容应该是不同的,而且第二次读出的内容应该是我们写进的字符串。字符串是保存在数据段中的,也是新增加的。增加的两个段如下所示:

LABEL_DESC_DATA:   Descriptor    0,      DataLen-1, DA_DRW    ; Data
LABEL_DESC_TEST:   Descriptor 0500000h,     0ffffh, DA_DRW

SelectorData		equ	LABEL_DESC_DATA		- LABEL_GDT
SelectorTest		equ	LABEL_DESC_TEST		- LABEL_GDT

[SECTION .data1]	 ; 数据段
ALIGN	32
[BITS	32]
LABEL_DATA:
BootMessage:		db	"Joey, I'm in protected mode!"
OffsetPMMessage		equ	BootMessage - $$		;表示字符串BootMessage相对于本节的开始处(LABEL_DATA)的偏移
StrTest:		db	"ABCDEFGHIJKLMNOPQRSTUVWXYZ", 0
OffsetStrTest		equ	StrTest - $$
DataLen			equ	$ - LABEL_DATA
; END of [SECTION .data1]

段[SECTION .s32]这个段的开头初始化了ds、es和gs,让ds指向新增的数据段,es指向新增的5MB内存的段,gs指向显存。如下所示:

LABEL_SEG_CODE32:
	mov	ax, SelectorData
	mov	ds, ax			; 数据段选择子
	mov	ax, SelectorTest
	mov	es, ax			; 测试段选择子
	mov	ax, SelectorVideo
	mov	gs, ax			; 视频段选择子(目的)

数据段的基址便是LABEL_DATA的物理地址。于是OffsetStrTest既是字符串相对于LABEL_DATA的偏移,也是其在数据段中的偏移。我们在保护模式下需要用到的正是这个偏移,而不再是实模式下的地址。section的一点妙用指的便是这里的$$。

	; 初始化数据段描述符
	xor	eax, eax
	mov	ax, ds
	shl	eax, 4
	add	eax, LABEL_DATA
	mov	word [LABEL_DESC_DATA + 2], ax
	shr	eax, 16
	mov	byte [LABEL_DESC_DATA + 4], al
	mov	byte [LABEL_DESC_DATA + 7], ah

运行如下所示:

第一次执行call TestRead时显示8个空字符,第二次执行call TestRead时显示ABCDEFGH。因为TestRead的段寄存器指向的是5MB内存地址处的内容,一开始是没有任何数据。

TestRead:
	xor	esi, esi
	mov	ecx, 8
.loop:
	mov	al, [es:esi]
	call	DispAL
	inc	esi
	loop	.loop

	ret

然后第190行向这个5MB内存地址处依次写入8字节数据。

一个码农的日常 

源码及软盘映像

原文地址:https://www.cnblogs.com/joey-hua/p/5371402.html