30天自制操作系统Day5

一、增加字体

hankaku.txt
  |makefont.exe将文本文件输出为二进制文件
hankaku.bin
  |bin2obj.exe将二进制文件加上连接所必需的接口信息,转换为目标程序
hankaku.obj

二、GDT(global segment descriptor table)

为了使操作系统能够同时运行多个程序,需要对内存进行分段,每一个段的起始地址都看作0来处理,为了保证程序能正常运行,就必须从物理内存中找到各个逻辑段的存放位置,为此,为每个进程建立一张段映射表,简称“段表”。
每个段对应一个段表项,段表项纪录了如下信息:

  1. 段的大小
  2. 段的起始地址
  3. 段的管理属性

每个段表项的长度固定,为8个字节,段表项的具体信息如下:

Segment Descriptor(段描述符):
在这里插入图片描述
Base(基地址):一个32位的值,包含段开始的线性地址。分为low(2字节)、mid(1字节)、high(1字节),分为三段是为了与80286时代的程序兼容,有了这样的规格,80286上的操作系统可以不用修改就在386以后的CPU上运行。
Limit(段界限):一个20位的值,以1字节单位或4KB页面表示最大可寻址单元。因此,如果选择页面粒度并将限制值设置为0xFFFFF,则该段将在32位模式下跨越整个4 GiB(2^20*4KB)地址空间。

Access Byte(访问字节,80286时代就已经存在):
在这里插入图片描述
Pr:段存在位,用于表示描述符所对应的段是否存在。
  Pr=0,表示段不在内存中。
  Pr=1,表示段在内存中。
Privl:描述符特权级别字段。包含段的CPU特权级别。0=最高权限(内核),3=最低权限(用户应用程序)。
S:用于指定描述符的类型。
  S=0,表示这是一个系统段;
  S=1,表示这是一个代码段或数据段(堆栈段也是特殊的数据段)。
Ex:表示是否可执行。
  Ex=0,表示不可执行,数据段总是不可执行的;
  Ex=1,表示可执行,代码段总是可执行的。
DC:
  对于数据选择器:表示段的扩展方向。
    D=0,向上扩展,即向高地址方向扩展,是普通的数据段;
    D=1,向下扩展,即向低地址方向扩展,通常是堆栈段。
  对于代码选择器:段特权级依从。
    C=0,表示非依从的代码段,可以与特权级相同的代码段调用,或者通过门调用;
    C=1,表示运行从低特权级的程序转移到该段执行。
RW:
  对于数据段:段是否允许读出。
    W=0,不允许写入,此时写入的话会引发异常中断;
    W=1,允许写入。
  对于代码段:段的写属性。
    R=0,表示代码段不能读出,此时读出会引发处理器异常中断;
    R=1,表示代码段可以读出。
Ac:已访问位,用于表示它指向的段最近是否被访问过。在描述符创建的时候应该清0。之后每当该段被访问时,处理器将该位置1。

常见的几种访问位:
0000000(0x00):未使用的记录表
10010010(0x92):系统专用,可读写的段,不可执行
10011010(0x9a):系统专用,可执行的段,可读不可写
11110010(0xf2):应用程序用,可读写的段,不可执行
11111010(0xfa):应用程序用,可执行的段,可读不可写

Flags(扩展访问权,80286时代还不存在):
在这里插入图片描述

Gr:粒度位,用于解释段界限的含义。
  G=0,段界限以字节为单位,段的扩展范围为1B~1MB(描述符的界限值为20位);
  G=1,段界限以页面(4KB)为单位,段的扩展范围为4KB~4GB
Sz:默认的操作数大小。主要是为了能够在32位处理器上兼容运行16位保护模式的程序。
  Sz=0,表示指令中的偏移地址或者操作数是16位的;
  Sz=1,表示偏移地址或者操作数是32位的。
L:64位代码段标志。如果设置为1,描述符将定义64位代码段。设置时,Sz应始终为0。对于任何其他类型的段(其他代码类型或任何数据段),将该位清0。

struct SEGMENT_DESCRIPTOR {
	short limit_low, base_low;
	char base_mid, access_right;
	char limit_high, base_high;
};

void set_segmdesc(struct SEGMENT_DESCRIPTOR *sd, unsigned int limit, int base, int ar)
{
	if (limit > 0xfffff) {
		ar |= 0x8000;	//粒度位设置为1
		limit /= 0x1000;	//以页面(4KB)为单位
	}
	sd->limit_low    = limit & 0xffff;	//段界限低16位
	sd->base_low     = base & 0xffff;	//基地址低16位
	sd->base_mid     = (base >> 16) & 0xff;	//基地址中8位
	sd->access_right = ar & 0xff;	//访问权
	sd->limit_high   = ((limit >> 16) & 0x0f) | ((ar >> 8) & 0xf0);	//段界限高4位和扩展访问权
	sd->base_high    = (base >> 24) & 0xff;	//基地址高8位
	return;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值