小试保护模式

前几天将段式保护模式从理论上了解了。所以这几天就借助一些书籍和网络得力量来争取实践---将代码跳入保护模式。
首先了解跳入保护模式的基本步骤
1、将代码段基址存入GDT
2、利用lgdt将GDT基址以及长度加载到gdtr寄存器
3、关中断
4、打开20号地址线
5、置位CR0的PE,准备切换
6、跳入保护模式下的代码段

下面就是这个简单跳跃得代码:
pm.inc包含一些宏定义以及段的属性定义值
 %macro Descriptor 3 
          dw  %2 & 0ffffh 
          dw  %1 & 0ffffh 
          db  (%1>>16) & 0ffh 
          dw  ((%2>>8)&0f00h)|(%3 & 0f0ffh) 
          db  (%2>>24)&0ffh 
 %endmacro 
  
 DA_32       equ     4000h   ;32位段 
  
 DA_DPL0     equ     00h     ;DPL=0 
 DA_DPL1     equ     220h    ;DPL=1 
 DA_DPL2     equ     40h     ;DPL=2 
 DA_DPL3     equ     60h     ;DPL=3 
  
 DA_DR       equ     90h     ;只读数据段 
 DA_DRW      equ     92h     ;可读可写数据段 
 DA_DRWA     equ     93h     ;可读可写已访问数据段 
 DA_C        equ     98h     ;只执行代码段 
 DA_CR       equ     9ah     ;可读可执行代码段 
 DA_CCO      equ     9ch     ;非一致可执行代码段 
 DA_CCRO     equ     9eh     ;可读非一致可执行代码段
 


protec.asm这是主要逻辑部分。功能实现得主体
%include "pm.inc"

org		07c00h
jmp		START

[SECTION .gdt]
GDT_DEC:		Descriptor  0,	0,	0
CODE32_DEC:		Descriptor  0,Code32Len-1,DA_32 + DA_CR	
VIDEO_DEC:		Descriptor  0b8000h,0ffffh	,DA_DRW

GdtLen	equ		$ - GDT_DEC	
Gdtptr	dw		GdtLen - 1
		dd		0

SelectorCode32	equ		CODE32_DEC - GDT_DEC
SelectorVideo	equ		VIDEO_DEC - GDT_DEC

[SECTION .s16]
[BITS 16]
START:
	mov		ax,cs
	mov		ds,ax
	mov		es,ax
	mov		ss,ax
	mov		sp,0100h
        ;加载代码段基址到GDT描述符
	xor		eax,eax
	mov		ax,cs
	shl		eax,4
	add		eax,CODE32_SEG
	mov	word [CODE32_DEC+2],ax
	shr		eax,16
	mov	byte [CODE32_DEC+4],al
	mov	byte [CODE32_DEC+7],ah
        ;加载GDT基址及长度到gdtr
	xor		eax,eax
	mov		ax,ds
	shl		eax,4
	add		eax,GDT_DEC
	mov	dword [Gdtptr+2],eax

	lgdt	[Gdtptr]
        ;关中断
	cli
        ;打开A20
	in		al,92h
	or		al,02h
	out		92h,al
        ;置位PE
	mov		eax,cr0
	or		eax,01h
	mov		cr0,eax
        ;跳转保护模式
	jmp		dword	SelectorCode32:0
[SECTION .s32]
[BITS 32]
CODE32_SEG:
	mov		ax,SelectorVideo
	mov		gs,ax
	mov		esi,offMessage
	mov		edi,(80*12+30)*2
	mov		ah,0ch
	cld
	call	DesplayMessage
Message:	db "Welcome protected place",0
offMessage	equ	Message - $$
DesplayMessage:
	.2:	
		mov		al,[cs:esi]
		test	al,al
	.1:
		jz		.1	
		mov		[gs:edi],ax
		add		edi,2
		inc		esi
		jmp	.2
Code32Len	equ		$	-  CODE32_SEG



不要值抄写代码运行,一旦代码不能带到目的就重抄一遍。这是不可取得。一定要自己慢慢调试,从内存角度理解每一条指令所起得作用,从内存去查看代码不能达到目的的原由。当然代码不可能一次成功,所以Bochs自带调试命令。
1、在某个物理地址设置断点
b addr            b 0x7c00

2、显示当前所有断点的信息
info break

3、继续执行直到遇到断点
c

4、单步执行
s

5、单步执行,遇到函数则跳过
n

6、查看寄存器信息
info cpu
r
fp
sreg
creg

7、查看堆栈
print-stack

8、查看内存物理地址内容
xp /nuf addr           xp /40bx  0x9013e
其中nuf表示大小,addr表示首地址

9、查看线性地址内容
x /nuf addr           x /40bx 0x13e

10、反汇编一段内存
u start end          u 0x30400 0x3040d

11、反汇编执行的每条指令
trace-on

12、每执行一条指令就打印cpu信息
trace-reg on
关闭trace-reg off
下面就是上述代码得结果。在屏幕中打印了一行红色的字



猜你喜欢

转载自tviker.iteye.com/blog/1473614