三十天自制操作系统(2)

第4天

今天一模一样开始也学最后学的用汇编写一个力所能及被C语言调用的函数,函数名叫write_mem8,功能是当指定内容遭形容副一定的数额。这个函数有三三两两只参数,第一独参数表示目标地点,第二个参数表示写副的数量。

斯函数最要之功效就是奔指定的内存地址中形容副数据,那么因此C语言可不可能也指定一个内存地址呢?其实是足以的,使用C语言中指针的概念就好了。C语言中所谓的指针其是就是是平常所谓的内存地址。比如想只要往0xa0000内存地址中描写副数据,可以这么:

int i;
char* p;
i  = 0xa0000;
p = (char*)i;
*p = i;

这么就是把变量i
中的情节写及外存0xa0000中了,而这个地址便是眼前写的操作系统被的显存地址,往这地方写副数据就是一定给以屏幕及写上情。

在进入32员之前,用BIOS中断把显卡设置成调色板模式。要描写设置显卡中之调色板,只能使汇编语言中之in和out指令。首先以挡中断;将惦念要设定的调色板号码写入0x03c8,按RGB序顺写入0x03c9,如果还要继续写入,只待连续写入0x03c9;如果假定读来调色板状态,将调色板的号码写入0x03c7,再从0x03c9读博3软,调出的相继是RGB,如果只要读博下一个,只要继续从0x03c9中调取下一个调色板;结束以后,取消中断屏蔽。

停顿屏蔽指令:

CLI(clear interrupt flag)

取消中断屏蔽指令:

STI(set interrupt flag)

依据C语言的确定,汇编中放入eax中的多少就是C语言的回值。

第五天

于32号CPU的模式下操作系统中显示字符和当屏幕上画的规律是平等的,字符只是平栽奇特之图样。本书里把一个字符定义也8*16独像从的位图,那么一个字符就占有16字节。一般以写字符方便,而且操作系统为支持不同字功能,会另外单独定义一个字文件,这个操作系统会当加载内存的当儿将书数据读入内存中。如果定义ASCII编码的256单字符,每个字符16字节,那么一共4096独字节,还好承受。

sprintf(地址, 格式,值,值,值,....)

至于格式的详细说明:

  1. %d,单纯的十上制数
  2. %5d,5位十向前制数
  3. %05d,在前方补0,强制达到时5各类
  4. %x,单纯十六进制数字母用小写
  5. %X,单纯十六进制数字母用大写

每当屏幕上显示鼠标,也即是以屏幕上画画一个图像。本书把鼠标定义也16*16个如从的位图,每个像素是8只字节,总共256独字节。鼠标图像来三种颜色,第一是鼠标的边缘,我们定义也黑色,位图中之所以*表标;第二单是鼠标本身的水彩,我们定义为黑色,位图被用0表示;第三单凡是背景色,就是匪显得颜色,用背景色补充,用.代表。

当32员CPU模式下,内存需要分段,为了表示一个段子,需要三单消息:1、段的尺寸;2、段的胚胎地址;3、段的管理性(禁止写副,禁止实施,系统专用等)。CPU用8独字节表示这些信,但是段寄存器只出16各项。表示的主意与调色板很一般,先出一个段选择符,存放于段寄存器里,然后于内存中先行设定这8只字节的音信。16各类段寄存器的低3各项非克采取,能因此底独来13个,所以一共能表示8192独段落。每个段落用8个字节表示,那么一共要8192*8=64KB表示,这64KB的数量就是是GDT:global
descriptor
table,全局段号记录表。GDT存入在内存的某个地方,然后将内存的开场地址及实惠设定个数存放于CPU的GDTR(global
descriptor table rigister)中。

IDT就是刹车记录表(interrupt descriptor
table),当CPU遇到抛锚后,暂时已正在处理的职责,转而行中断程序。IDT记录了0~255的暂停号码和调用函数的照应关系,设定方法与GDT很相像。而且要事先设定GDT再设定IDT。设定IDT的目的是思念叫咱的操作系统对鼠标的倒作出反应。

第六天

就此C语言写的操作系统源文件bootpack.c已经非常丰富了,现在设想要以自文件依据不同之效应拆分开来。分成三个组成部分:1、关于屏幕上画的一部分graph.c;2、关于GDT\IDT设置的一些dsctbl.c;3、其他处理bootpack.c

鉴于来自文件多了相应的Makefile里的编绎规则也便大多了。Makefile有一个技术可拿类似的转变规则

%.gas : %.c Makefile
  $(CC1) -o $*.gas $*.c

%.nas : %.gas Makefile
  $(GAS2NASK $*gas $*.nas

make.exe会先物色普通的浮动规则,如果无找到,就尝试用一般规则。

C语言中之include有<>和“”的区别,前者表示头文件在编绎器的文件夹着,后者表示头文件在自文件所在的公文夹着。

_load_gdtr ; void load_gdtr(int limit, int addr); 
  mov ax, [esp + 4]; limit
  mov [esp + 6], ax
  lgdt [esp + 6]
  ret

斯函数将点名的截上限和地方赋值给GDTR这个48各寄存器,也就算是6个字节。低16个存放段上限,它相当GDT的管事字节数-1,剩余的4独字节代表GDT的起地址。上面程序将传播的参数limit低2字节移到强2字节,然后实施lgdt指令。

GDT中各一个段落信息用8个字节表示,写的操作系统中一个定义了一个结构体表示。

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

段的地方也给做段基础,用32号代表,在结构体中因故4独字段表示,分别是base_low(2个字节),
base_mid(1个字节), base_high(1单字节)。正好合4只字节。

段的大大小小也吃做段上限,结构体中之所以3单字节表示,分别是limit_low(2个字节),limit_high(1单字节)。虽然段上限我们组织体里使用了3独字节,但是实际上是行得通之不过发20各项,另外4各项代表段属性。limit_high的高4位代表段属性。段大小用20各类表示,那么一个段子最酷之一味出1MB。但是好透过段属性中之一个个设置成1就算可以拿段上限的单位从字节转换成页,一页表示4KB。那么20各段上限就足以不示4GB。

结构体中还有一个字段access_right,表示段属性,也深受做段的顾权属性。段属性一共用12只字节表示,高4位保存在limit_high字段的高4各备受,这4个而为称扩展访问权,这4位由GD00构成,G表示段上限字段的单位凡字节还是页(0表示字节,1意味页)。D字段表示段模式,1凡靠32个,0是依16员。access_right简单说明如下:

  1. 00000000(0x00): 未使用的笔录 段
  2. 10010010(0x92):系统专用,可读写,不可实践
  3. 10011010(0x9a):系统专用,可尽,可读不可写
  4. 11110010(0xf2):应用程序用,可读写,不可实践
  5. 11111010(0xfa):应用程序用,可实施,可读不可写

在用中断之前一定要是先期安装PIC,programmable interrupt
controller。电脑的刹车信用来15独,两个PIC,与CPU直接相接的叫做主PIC,与主PIC相连的PIC称为从PIC。从PIC通过2声泪俱下IRQ与主PIC相连。

PIC的拥有寄存器都是8员之,IMR是interrupt mask
register的缩写,中断屏蔽寄存器。8各类分别对诺8里程IRQ信号,如果有平等各设置也1虽说忽略该路信号。

ICW是initial control
word的缩写,为初始化控制数据,一共发生4单,编号分别吗1-4。ICW1、ICW3,ICW4的设定值也定位,操作系统唯一会安装的凡ICW2。ICW2表示IRQ以几哀号中断通知CPU。我们刻画的操作系统里把015号中断设置为0x200x2f号中断。

汇编指令pushad相当给

push eax
push ecx
push edx
push ebx
push esp
push ebp
push esi
push edi

彼此对应之吗生popad

想念让CPU处理搁浅,先勾勒中断的处理程序,然后再次将暂停处理程序的入口地址注册IDT中,等到中断信号发生的早晚,系统会自行调用中断处理程序。