首页 > 其他分享 >5.9 GDT与IDT的初始化(harib02i)

5.9 GDT与IDT的初始化(harib02i)

时间:2023-03-15 21:47:22浏览次数:36  
标签:GDT 字节 5.9 IDT high harib02i limit low base

5.9 GDT与IDT的初始化(harib02i)

CPU用8字节来表示一个段的1.段的大小2.段的起始地址3.段的管理属性(禁止写入,禁止执行,系统专用)信息,但8字节(64位)远大于段寄存器(16位),故用段寄存器来存储段号,由于16位中的低三位不能用,故只有0~8191的区域,即8192个段8192*8=68836字节(64kb),64kb的数据CPU无法储存,故存储在内存中,这64kb的数据即为GDT(global(segment) descriptor table)全局段号记录表,而为了使用GDT方便,便将GDT的首地址有效设定个数存入GDTR(global(segment) descriptor table register)特殊寄存器中

  • GDT:global(segment) descriptor table 全局段号记录表

  • 段寄存器:16位

  • IDT:interrupt descriptor table 中断记录表 IDT记录了0~255的中断号码与调用函数的对应关系,其设定方法与GDT相似(也许是因为使用同样方法可以简化CPU电路

注意:设定IDT(interrupt descriptor table)最好先于设定GDT(global(segment) descriptor table),否则会比较麻烦

/*SEGMENT_DESCRIPTOR与GATE_DESCRIPTOR一样,均是以CPU的资料为基础,写成结构体的形式*/
struct SEGMENT_DESCRIPTOR {//8字节=2*2字节+2*1字节+2*1字节
	short limit_low, base_low;//short类型占两字节
	char base_mid, access_right;
	char limit_high, base_high;
};

struct GATE_DESCRIPTOR {//8字节=2*2字节+2*1字节+1*2字节
	short offset_low, selector;//short类型占两字节
	char dw_count, access_right;
	short offset_high;
};
void init_gdtidt(void)
{
    /*表明要使用内存0x00270000~0x0027ffff的65535B设为GDT,原因是这一块内存未被使用*/
	struct SEGMENT_DESCRIPTOR *gdt = (struct SEGMENT_DESCRIPTOR *) 0x00270000;
    /*表明要使用0x0026f800~0x00270000的2048B设为IDT,这也应证了“有256个中断号码,用8B表示每个中断对应的信息”*/
	struct GATE_DESCRIPTOR    *idt = (struct GATE_DESCRIPTOR    *) 0x0026f800;
	int i;
	/* global(segment) descriptor table  全局短号记录表*/
	/* GDT初始化 */
	for (i = 0; i < 8192; i++) {/*此处要注意C语言进行指针的加法运算时,内部隐含着乘法运算*/
		set_segmdesc(gdt + i, 0, 0, 0);
	}
    /*设定,段号为1的段,上限值为0xffffffff(即大小正好是4GB),地址是0,它表示的是CPU所能管理的
全部内存本身。段的属性设为0x4092,它的含义我们留待明天再说*/
	set_segmdesc(gdt + 1, 0xffffffff, 0x00000000, 0x4092);
    /*段号为2的段,它的大小是512KB,地址是0x280000。这正好是为bootpack.hrb而准备的。这个段可以执行bootpack.hrb。因为bootpack.hrb是以ORG 0为前提翻译成的机器语言。*/
	set_segmdesc(gdt + 2, 0x0007ffff, 0x00280000, 0x409a);
	load_gdtr(0xffff, 0x00270000);/*同下方的load_idtr(0x7ff, 0x0026f800);,C语言不能给GDTR赋值*/

	/* interrupt descriptor table  中断记录表*/
	/* IDT初始化 */
	for (i = 0; i < 256; i++) {
		set_gatedesc(idt + i, 0, 0, 0);
	}
	load_idtr(0x7ff, 0x0026f800);

	return;
}
//上限(limit,指段的字节数-1),基址(base),访问权限
void set_segmdesc(struct SEGMENT_DESCRIPTOR *sd, unsigned int limit, int base, int ar)
{
	if (limit > 0xfffff) {
		ar |= 0x8000; /* G_bit = 1 */
		limit /= 0x1000;
	}
	sd->limit_low    = limit & 0xffff;
	sd->base_low     = base & 0xffff;
	sd->base_mid     = (base >> 16) & 0xff;
	sd->access_right = ar & 0xff;
	sd->limit_high   = ((limit >> 16) & 0x0f) | ((ar >> 8) & 0xf0);
	sd->base_high    = (base >> 24) & 0xff;
	return;
}
void set_gatedesc(struct GATE_DESCRIPTOR *gd, int offset, int selector, int ar)
{
	gd->offset_low   = offset & 0xffff;
	gd->selector     = selector;
	gd->dw_count     = (ar >> 8) & 0xff;
	gd->access_right = ar & 0xff;
	gd->offset_high  = (offset >> 16) & 0xffff;
	return;
}

此处将6.4中的内容提前到此处

_load_gdtr:		; void load_gdtr(int limit, int addr);
		MOV		AX,[ESP+4]		; limit
		MOV		[ESP+6],AX
		LGDT	[ESP+6]			;将从地址[ESP+6]起的6字节数据赋值给GDTR寄存器
		RET

_load_gdtr函数的功能是将段上限(limit)地址值赋值给名为GDTR(global(segment) descriptor table register)48 位寄存器。注意:GDTR不能用正常的MOV指令进行赋值,只能使用LGDT指令

关于GDTR寄存器,其低16位(即内存的最初2个字节)是段上限(即GDT 的有效字节数 - 1),剩下的高32位, 代表GDT的开始地址

经过上图的变换,即可完成写入GDT的任务。

注意:从ESP到ESP+3的四字节空间应该是被函数_load_gdtr的什么属性占据了,查明资料后补充

struct SEGMENT_DESCRIPTOR {//8字节=2*2字节+2*1字节+2*1字节
	short limit_low, base_low;//short类型占两字节
	char base_mid, access_right;
	char limit_high, base_high;
};

结构体中base分为low(2字节),mid(1字节),high(1字节) 3段,合起来刚好是32位。分三段是为了与80286时代的程序兼容,这样80286用的操作系统,可以不用修改就在386以后的CPU上运行了。

//上限(limit,指段的字节数-1),基址(base),访问权限
void set_segmdesc(struct SEGMENT_DESCRIPTOR *sd, unsigned int limit, int base, int ar)
{
	if (limit > 0xfffff) {
		ar |= 0x8000; /* G_bit = 1 */
		limit /= 0x1000;
	}
	sd->limit_low    = limit & 0xffff;
	sd->base_low     = base & 0xffff;
	sd->base_mid     = (base >> 16) & 0xff;
	sd->access_right = ar & 0xff;
	sd->limit_high   = ((limit >> 16) & 0x0f) | ((ar >> 8) & 0xf0);
	sd->base_high    = (base >> 24) & 0xff;
	return;
}

也正因为是三段,所以以上set_segmdesc函数中需要使用移位运算符和AND运算符来填入数据


由于段上限最大是4GB,即一个32位(4字节)数值,所以段大小占4字节,基址(base 起始地址)再占4字节,则段的管理属性没地方保存。若想保存段的管理属性,则段的大小只能使用20位,则可以使用的段上限缩小为1MB。故因特尔的解决办法是给段增加一个属性——Gbit,该标志位为1时,将limit的单位解释为页(4KB),1M*4KB=4GB,则不会产生浪费。因此20位的段上限写到limit_low(2字节)limit_high(1字节)的低四位中,limit_high(1字节)的高四位写入段属性(还有一部分在access_right)。

access_right或ar的高4位(即limit_high(1字节)的高四位)被称为“扩展访问权”,因为它在80286时代不存在386后才可以用。这四位由“GD00”构成,G为上文中的Gbit标志位,D为段的模式(1是指32位模式,0是指16位模式),这里的16位模式主要只用于运行 80286的程序不能用于调用BIOS。所以,除了运行80286程序以外, 通常都使用D=1的模式。

access_right或ar的低4位在80286时代就已经有了,下面简单介绍以下

00000000(0x00):未使用的记录表(descriptor table)。
10010010(0x92):系统专用,可读写的段。不可执行。
10011010(0x9a):系统专用,可执行的段。可读不可写。
11110010(0xf2):应用程序用,可读写的段。不可执行。
11111010(0xfa):应用程序用,可执行的段。可读不可写。

32位模式下,CPU有系统模式(也称为“ring0”)应用模式(也称为“ring3”)

举例:在应用模式下不允许执行LGDT指令(从指定的地址读取6个字节(48位),然后赋值给GDTR),一旦可以执行LGDT便可以修改GDTR,从而对GDT进行修改

struct SEGMENT_DESCRIPTOR {//8字节=2*2字节+2*1字节+2*1字节
	short limit_low, base_low;//short类型占两字节
	char base_mid, access_right;
	char limit_high, base_high;
};

标签:GDT,字节,5.9,IDT,high,harib02i,limit,low,base
From: https://www.cnblogs.com/LZHKKK/p/17220163.html

相关文章

  • clientHeight、clientWidth innerHeight innerWidth
    https://www.runoob.com/jsref/prop-win-innerheight-innerwidth.htmlinnerHeight返回窗口的文档显示区的高度,如果有垂直滚动条,也包括滚动条高度。innerWidth返回窗口......
  • jquery获取设置元素宽高位置height()、width()、offset()、position()、scrollTop()、
    ​​​​全栈工程师开发手册(作者:栾鹏)​​jquery系列教程2-style样式操作全解​​jquery获取设置元素宽高位置jquery的通过height()、width()、offset()、position()、s......
  • docker部署gitlab 15.9
    docker-compose.ymlversion:'3.6'services:web:image:'gitlab/gitlab-ce:15.9.1-ce.0'restart:alwayshostname:'project.example.com'contai......
  • 5.9.2宝塔面板安装php7.3
    在宝塔目录:/www/server/panel/install/php.sh  中包含了全部的安装php命令,可以找到php7.3的。然后用ssh运行  bash/www/server/panel/install/php.shinstall 7.3......
  • 《优爱酷玩转机顶盒》实战系列№2:机顶盒Root教程推送SuperUser.apk超级授权文件(附下载
        Root成功            再次声明:刷机有风险,请自行斟酌,风险自负。优爱酷对使用本程序或教程可能造成的不良后果不承担任何法律或道......
  • 优爱酷玩转机顶盒实战系列AndroidTV
    优爱酷玩转机顶盒实战系列AndroidTV  介绍优爱酷玩转机顶盒实战系列AndroidTV。请关注【优爱酷】回复【机顶盒】查阅《优爱酷玩转机顶盒》实战实录系列文章......
  • Schmidt-Samoa密码系统
    Schmidt-Samoa密码系统Schmidt-Samoa密码系统,像rabin加密一样,其安全性基于整数因式分解的难度。但Rabin解密时会得到四个解,而Schmidt-Samor得到的是唯一解。密钥生成......
  • AndroidThings学习笔记--gpio控制Led和Button
    1.了解androidthings的框架  Androidthings框架,其实和android原生区别不是非常的大。如下图所示:  AndroidThings扩展了一些硬件相关的api,比如外设io的api,以及用户驱......
  • AndroidThings学习笔记--熟悉RPI3硬件
      在学习写代码前,还是先了解下硬件,也就是所谓的树莓派,相信很多人即使没有玩过,也是听过的,世界上最小的电脑。毕竟是玩物联网,玩硬件,不需要太多的硬件知识,但是基础的还是需要......
  • Subtitle Edit v3.5.9
    免费开源且支持超过200种格式的字幕编辑工具。提供安装,免安装,免安装带字典版本;支持包括简体中文在内的超过33种语言。下载:​​​​​https://github.com/SubtitleEdi......