三十天自制操作系统(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中,等到中断信号发生的时候,系统会自动调用中断处理程序。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260

推荐阅读更多精彩内容

  • 第7天 PIC初始化之后,再写中断处理函数,然后把中断处理函数的入口地址注册在IDT中。现在重点是中断处理函数如何...
    whatcanhumando阅读 931评论 0 0
  • 8086汇编 本笔记是笔者观看小甲鱼老师(鱼C论坛)《零基础入门学习汇编语言》系列视频的笔记,在此感谢他和像他一样...
    Gibbs基阅读 36,305评论 8 113
  • 一、温故而知新 1. 内存不够怎么办 内存简单分配策略的问题地址空间不隔离内存使用效率低程序运行的地址不确定 关于...
    SeanCST阅读 7,665评论 0 27
  • 第27天 前一天讲到为什么用ncst命令之后应用程序就无法关闭了。现在看一下程序ncst到底干了什么事情。如果在命...
    whatcanhumando阅读 1,449评论 1 5
  • 老公:你每天一如既往的对家和孩子的思念,谢谢你的付出,克服一个人在外的孤独。 女儿:放学后早早的把明天要考试的东西...
    鲁慧阅读 115评论 0 0