《30天自制操作系统》笔记(06)——CPU的32位模式

《30天自制操作系统》笔记(06)——CPU的32位模式

进度回顾

上一篇中实现了启用鼠标、键盘的功能。屏幕上会显示出用户按键、点击鼠标的情况。这是通过设置硬件的中断函数实现的,可以说硬件本身的设计就具有事件驱动的性质,所以软件层面上才有基于事件的消息机制。

但上一篇没有说明中断的来龙去脉,本篇就从头到尾描述一下CPU与此相关的设置问题。

Segment

32位的CPU使用32条地址线,能区分232=4G个内存地址。每个内存地址都有1Byte的内容。

分段,就是将4GB的内存分成很多块(block),每一块的起始地址都看作0来处理。有了这个功能,任何程序都可以先写上一句"ORG
0",一个应用程序就不会占用别人的内存空间,这样就可以同时运行多个程序。像这样分割出来的块,就称为段(segment)。还有一种"分页"的技术,这里不讨论。

为了表示一个段,需要记录以下信息:

  • 段的起始地址

  • 段的大小

  • 段的管理属性(禁止写入,执行,系统专用等)

这些信息需要用8个字节保存。使用段的方式是和调色板神似的:DS是16位,理论上能够表示216=65536个段。但由于CPU设计上的原因,低3位不能用,因此DS只能表示213=8192个段(即第0个~第8191个)。

在16位模式下,如果写"MOV AL, [DS:EBX]",那么要计算的地址是DS*16+EBX。在32位模式下,则应该是DS表示的段(segment)的起始地址+EBX。

另外,如果写成"MOV AL, [EBX]",则汇编器认为这等同于"MOV AL, [DS:EBX]"。这一点在16位和32位模式下是一致的。

要存储8192个段,就需要占用9102*8=65536Byte=64KB的内存空间。这64KB的数据就称为GDT
(Global segment Descriptor Table)即"全局段号记录表"。

将这64K的GDT整齐地排列在内存某处,再将其起始地址和有效设定个数放在CPU内被称作GDTR的48bit寄存器中,GDT的设定就完成了。

段的起始地址、大小、管理属性这些信息是按bit保存的,十分复杂,暂时不要理会。

IDT

当CPU遇到外部情况变化,或是内部发生某些错误时,会临时切换过去处理这种突发事件。这就是中断功能。键盘按键、鼠标按键、鼠标移动、除0等都会引发中断。有了中断机制,CPU就不需要一直查询这些低速设备的状态,将时间用在处理任务上。

因此,要使用鼠标键盘,就必须使用中断机制,即设置IDT。

IDT(Interrupt Descriptor
Table)即"中断记录表"。IDT记录了0~255的中断号与调用函数之间的对应关系。当发生了123号中断,就会调用对应的函数。其设置方式与GDT是相似的,IDT的每一项也需要8Byte保存,这8Byte里包括中断处理函数名(即C语言中的函数指针)。

另外,必须先设置GDT后设置IDT。原因不详。

PIC

PIC(Programmable Interrupt Controller)即"可编程中断控制器"。它是一个硬件芯片。

当键盘鼠标发生按键、移动时,PIC就会向CPU发送电信号,然后CPU要求PIC发送2个Byte来(其内容为"0xcd
0x??",实际上是机器语言的INT指令),CPU还真就把PIC送来的这2个Byte看作一条指令执行。其结果是调用IDT中对应的函数。

PIC送来的PIC的设定基本上都是固定死的几行代码,暂时不用理会。

进入32位模式

进入32位模式实际上很简单,按照一定的步骤将某些寄存器(CR0等)设置为特定的值就行了。也有点繁琐,暂时不理会。

操作系统程序被加载到内存中的什么地方才行?这个没有特别的规定,根据自己的偏好分给OS一些内存空间就行了。不过有些内存空间放着BIOS等程序,而且大部分高地址的内存是要给应用程序使用的。因此OS程序的空间分配也不要太随意了。下图是HariboteOS设计的内存分布图。

总结

本文以轻量从简的态度简单说明了OS启动时要初始化的大部分东西,即GDT、IDT、PIC、32位模式。我个人认为这些都是细节,应该进行封装。后续的内存管理、多任务才是OS设计的核心内容。

请查看下一篇《《30天自制操作系统》笔记(07)——内存管理》

时间: 2024-10-18 11:46:20

《30天自制操作系统》笔记(06)——CPU的32位模式的相关文章

30天自制操作系统笔记(第四天)

这一节讲的最出彩的地方是c语言的地址. 而要理清c语言地址,又必须追根溯源,看看汇编里内存地址的使用. MOV AL,0X15 MOV [1024],AL MOV BYTE[1024],0X15 这两种指令效果相同,都是在这个内存地址里存入一个数据,而学过汇编的我们知道,直接往内存某地址存入数据时,要说明填入的数据大小,或者说数据类型,不然机器不知道怎么填入该数据,到底是按照8位填入,还是十六位填入.因此,这个byte必不可少,而前面的指令,由于AL已经明确了是八位,因此不用说明. 好了,接下来

《30天自制操作系统》读书笔记(2)hello, world

让系统跑起来 要写一个操作系统,我们首先要有一个储存系统的介质,原版书似乎是06年出版的,可惜那时候没有电脑,没想到作者用的还是软盘,现在的电脑谁有软驱?不得已我使用一张128M的SD卡来代替,而事实上你用的是U盘还是软盘对我们的操作系统没有影响,缺点是你的U盘刷入系统后容量只能是1440 MB,即当年流行的3.5英寸软盘的大小,当然不用担心,再格式化一次(用DiskGeniu),就可以恢复. 我做事情的话,总是怕自己的努力的结果白费了,害怕辛辛苦苦看完这本书但是发现做出来的东西现在根本没法用,

《30天自制操作系统》笔记(12)——多任务入门

<30天自制操作系统>笔记(12)——多任务入门 进度回顾 上一篇介绍了设置显示器高分辨率的方法.本篇讲一下操作系统实现多任务的方法. 什么是多任务 对程序员来说,也许这是废话,不过还是说清楚比较好. 多任务就是让电脑同时运行多个程序(如一边写代码一边听音乐一边下载电影). 电脑的CPU只有固定有限的那么一个或几个,不可能真的同时运行多个程序.所以就用近似的方式,让多个程序轮换着运行.当轮换速度够快(0.01秒),给人的感觉就是"同时"运行了. 多任务之不实用版 我们首先从

《30天自制操作系统》笔记(01)——hello bitzhuwei’s OS!

<30天自制操作系统>笔记(01)--hello bitzhuwei's OS! 最初的OS代码 1 ; hello-os 2 ; TAB=4 3 4 ORG 0x7c00 ; 指明程序的装载地址 5 6 ; 以下这段是标准FAT32格式软盘专用的代码 7 8 JMP entry 9 DB 0x90 10 DB "HELLOIPL" ; freeparam 启动区的名称可以是任意的字符串(8字节) 11 DW 512 ; 每个扇区(sector)的大小(必须为512字节)

《30天自制操作系统》笔记(02)——导入C语言

<30天自制操作系统>笔记(02)--导入C语言 进度回顾 在上一篇,记录了计算机开机时加载IPL程序(initial program loader,一个nas汇编程序)的情况,包括IPL代码(helloos.nas).编译生成helloos.img文件.用虚拟机QEMU加载helloos.img.制作U盘启动盘和用物理机加载helloos.img. 计算机启动时会自动加载和执行IPL程序,但IPL程序只能占用512字节.若直接用IPL写OS,空间不够用.所以IPL程序一般用于将真正的OS程序

《30天自制操作系统》笔记(07)——内存管理

<30天自制操作系统>笔记(07)--内存管理 进度回顾 上一篇中处理掉了绝大部分与CPU配置相关的东西.本篇介绍内存管理的思路和算法. 现在想想,从软件工程师的角度看,CPU也只是一个软件而已:它的功能就是加载指令.执行指令和响应中断,而响应中断也是在加载指令.执行指令.就像火车沿着一条环形铁轨前进:当中断发生时,就好像铁轨岔口处变轨了,火车就顺着另一条轨迹走了:走完之后又绕回来重新开始.决定CPU是否变轨的,就是CPU里的特定寄存器. 这是题外话,就此为止. 什么是内存管理 假设内存大小是

《30天自制操作系统》笔记(13)——总结

<30天自制操作系统>笔记(13)——总结 进度回顾 上一篇介绍了操作系统实现多任务的方法.操作系统利用CPU的far模式的JMP指令.寄存器TR.GDT.TSS和PIT中断这些功能实现了多任务,可见CPU在设计时就考虑到了计算机要具有多任务处理的能力.也就是说,CPU.PIC等硬件支持什么功能,操作系统才能实现什么功能. 至此全书已经读了一半.我发现后半部分读不下去,也没必要再读了.本篇就对所有的笔记做一总结,至此<30天自制操作系统>这本书就暂且不读了. 所学所感 我们可以把C

《30天自制操作系统》读书笔记(5) GDT&amp;IDT

梳理项目结构 项目做到现在, 前头的好多东西都忘了, 还是通过Makefile重新理解一下整个项目是如何编译的: 现在我们拥有这么9个文件: ipl10.nas    InitialProgramLoader, 占用了软盘的第一个扇区并符合启动盘的规范, 默认被载入地址是0x7c00 到 0x7e00, 负责将10个柱面读入到0x8200到0x34fff (10个柱面共10*2*18 = 360 个扇区但是第一个没有被读入); asmhead.nas     包含一些暂时未知的设定; naskf

多定时器处理1(30天自制操作系统--读书笔记)

自认为写过很多MCU程序,但总是回头想想,我所了解的MCU编程思想大体有两种,其中具体的想法我得再找时间写下来. 总想总结出一个可扩展的,易移植的写法,但能力还没到这个层次.但<30天自制操作系统>这本书确实给我了一个思路,就像我已经写过的两篇读书笔记. 将两个独立的内容--FIFO和内存动态管理做到高度模块化,尤其是其中数据结构模型的设计更是我学习的好例子. 今天要学习的设计内容是多定时器处理.原书对这部分的处理讲的很详细,由浅入深,看得我由衷佩服作者,也可能是因为我水平低,稍稍看出点门道来