欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

在保护模式下编写程序

程序员文章站 2024-03-13 12:32:21
...

0.保护模式

       在8086的芯片里,你可以访问或修改任意一个内存单元。因为它只有一种工作方式,那就是实模式。
       8086可以一次性处理16位的数据,传送16位的数据,寻址1MB的内存,后来intel在80286上实现了16位保护模式,80286有24跟地址线,可以在保护模式下寻址16MB的内存,但是由于80286的寄存器仍然是16位的,所以段的长度不能超过64KB(16位保护模式已经很少为人知了),后来实现了32位的保护模式,机器在这种模式下具有32位的寄存器,32条地址线,最多可访问4GB的内存,但是为了兼容性,实模式还是保留了下来,可相比于最多寻址1MB的实模式,工作在保护模式下的机器才能以最高效率运行,除此之外最重要的一点,便是体现在“保护”二字之上。

1.GDT(全局描述符表)

       一开始我们提到的8086实模式,在这种工作模式下我们可以不受约束地修改或访问内存,在现在看来这是非常不合理的,因为你的程序有可能会发生不可预料的结果,从而转移到了别的程序的代码段里作修改,这样就会引发各种问题。
       于是便想到了在使用段之前应该先声明该段的起始地址,有多大等信息,这些信息叫做段描述符(Seg Descriptor)。我们用一块内存统一放置这些段描述符,这块内存叫做GDT,里面有多少项,说明有多少个段。为了保存这个GDT处理器内部使用一个48位的寄存器GDTR,低十六位保存"GDT边界",数值上等于 GDT的大小-1,实际上等于表内最后一字节的偏移地址,高32位表示GDT的起始地址。
关于SD,则是用一段8字节的数据结构来表示:
(高32位)
在保护模式下编写程序

1-1.G字段:1bit,决定段界限的单位,G为1时段界限以4KB为单位,G为0时以1B为单位。
1-2.D/B字段:1bit,表示默认的操作数大小,对于代码段,其称为D,D=1时处理器执行该段时使用EIP取指令,否则使用IP;对于栈段,称为B位,B=1时使用ESP,否则使用SP。
1-3. L字段:1bit,64位代码段标志。留给64位处理器使用。
1-4.AVL字段:1bits,留给操作系统使用。
1-5.P 字段: 1bit,当描述符访问内存中的段时,如果P=0处理器则产生一个异常中断。而操作系统则处理该过程,将该段从硬盘换回内存,并将P位置1.
1-6. DPL字段:2bits,表示特权级,一共有四种0,1,2,3,零级具有最高优先级。
1-7.S字段:1bit,s=1时表示这是一个代码段或数据段,s=0表示这是系统段。
1-8 TYPE字段:
(低32位)
在保护模式下编写程序

可以看出,虽然在64位的空间里表示32位的段基址和20位的段界限,它们分配的空间是非常断续的,于是编写这部分代码时要认真,先从SD开始,声明一个数据结构。

         编写这部分代码时,必须严格根据SD的结构

首先声明一个宏Descriptior,由三个参数组成,设为P1,P2,P3
P1代表段基址(32bits) ,P2代表段界限(20位),P3代表各个字段的值。

;--------Segment Descriptior
%marco Descriptor 3  ;表明这个宏由三个参数组成
	dw %2 & 0xFFFF  ;取段界限的低16位
	dw %1 & 0xFFFF  ;取段基址的低16位
	db (%1 >> 16) & 0xff ;取段基址的23~16位
	dw	((%2 >> 8) & 0F00h) | (%3 & 0F0FFh)
	db	(%1 >> 24) & 0FFh ;取段基址的31~24%endmarco

关于这条指令dw ((%2 >> 8) & 0F00h) | (%3 & 0F0FFh),是因为在SD中的第8位到第23位,关于属性的比特并不是连续的,必须从参数中分开取出,再用操作合并。

2.从实模式到保护模式

相关标签: 一个内核