自制操作系统
自制操作系统
才大难为用
我不懒
展开
-
自制操作系统(八)
现在是源代码,是需要编译的,整个过程是用nask也好,GCC也好,最后变成一个二进制文件而已,仅仅是一个文件而已,然后这个文件直接拷贝到内存,它掌控着所有,反正不管怎么说,现在初级阶段就进行分文件夹是不对的,没有什么意义。这回是要进行命名的,如何命名呢?常量,宏定义都是大写字母全局变量是l开头的,后面跟大写而不是下划线普通变量,开头小写,中间大写函数,如果有类就好了,但是没有类,有主谓型...原创 2020-02-28 17:24:05 · 141 阅读 · 0 评论 -
用自制编程语言写自制操作系统(一)
再讲讲自制编程语言,编程语言的话我没有特别推荐的,把编译原理学好就行了,我最开始用的是递归下降式文法,这里以过来人的身份告诉你,千万不要用这种文法,虽然这种文法比较简单,但是它太受限了,你根本无法设计出来令你满意的编程语言语法,当时设计到一半我就放弃了,自制编程语言一定要用递归向上式文法,虽然难的不行,但是它足够能让你随意设计任何语法,LR1文法足够用了。原创 2023-02-21 14:01:29 · 281 阅读 · 0 评论 -
ZOS 之 分段与分页
首先要进行分段还是分页?那要搞清楚分段和分页都是什么利用基址和界限寄存器,操作系统很容易将不同进程重定位到不同的物理内存区域。但是,对于这些内存区域,栈和堆之间,有一大块“空闲”空间。栈和堆之间的空间并没有被进程使用,却依然占用了实际的物理内存。因此,简单的通过基址寄存器和界限寄存器实现的虚拟内存很浪费。分段可以使软件的内存从0开始,每个软件自动分配一个基值,然后软件本身一直用变址,就是如此在典型的地址空间里有3个逻辑不同的段:代码、栈和堆。分段的机制使得操作系统能够将不同的段放到不同的物理内存原创 2021-12-06 10:57:02 · 433 阅读 · 0 评论 -
ZOS 之 浮点数寄存器
浮点执行环境的寄存器主要是8个通用数据寄存器和几个专用寄存器,它们是状态寄存器、控制寄存器、标记寄存器等8个浮点数据寄存器(FPU Data Register),编号FPR0 ~ FPR7。每个浮点寄存器都是80位的,以扩展精度格式存储数据。当其他类型数据压入数据寄存器时,PFU自动转换成扩展精度;相反,数据寄存器的数据取出时,系统也会自动转换成要求的数据类型。 8个浮点数据寄存器组成首尾相接的堆栈,当前栈顶ST(0)指向的FPRx由状态寄存器中TOP字段指明。数据寄存器不采用随机存取,而是按.原创 2021-12-03 11:29:00 · 1848 阅读 · 0 评论 -
ZOS 之 IPL,boot
在实模式下,不仅寻址方式奇怪,而且仅支持1MB的,相对于1.44MB的软盘,自然无法完全读取到。软盘第一个扇区是IPL,放到内存0x7c00,第二个扇区是boot,放到0x8000,实际上在IPL里读取这两个扇区,在IPL里实现32位模式切换,然后跳到boot这里,读取所有磁盘信息到内存,然后跳转执行到main,就是如此。...原创 2021-10-29 19:27:49 · 181 阅读 · 0 评论 -
NOS 之 阶段性整理
又断更了一个多月,现在应该是完全转移到自制编程语言上了,现在的话就是转置键盘,尽快生成命令行。移出去的代价,就是必须用高级语言写,这尤其不适合特殊汇编代码,这意味着你还要封装这些代码,但是呢,emmm,我希望除了基本的汇编封装,其他的都放到外面,只不过这时候先做紧急的,对吧。寄存器是否可以看中断?RPL: Requested Privilege Level, 请求特权级DPL: Descriptor Privilege Level,描述符特权级CPL: Current Privilege Lev原创 2021-03-28 11:30:09 · 144 阅读 · 0 评论 -
NOS 之 qemu实现
不仅仅有镜像,我们必须还要创建一个虚拟机才行,而不是每次都创建。而这就是qemu-img的作用。create [-ffmt] [-ooptions]filename[size]创建一个格式为fmt大小为size文件名为filename的磁盘镜像文件。或者说一个虚拟机。参数-ffmt是指定文件的格式,如果不指定格式qemu-img会自动检测,filename是磁盘镜像文件的名称(包括路径)。注意是磁盘镜像,而不是系统镜像。qcow2是QEMU 0.8.3版本引入的镜像文件格式,也是目...原创 2021-02-18 18:04:54 · 219 阅读 · 0 评论 -
NOS 之 转入C语言,链接
主要就是为了这个链接,有链接,就完全抛弃nasm的include的方式。首先,需要说明的是,64位模式下,nasm和c语言函数之间的参数传递是通过64位寄存器来进行的,而32位模式下,参数的传递则是通过栈来实现的,这一点区别很重要!!...原创 2021-02-15 16:11:39 · 128 阅读 · 0 评论 -
NOS 之 NASM,汇编链接问题
在function文件里写这个:global _func在main文件里写这个extern _func然后编译时都先用nasm编译成obj,然后用ld链接到一块。nasm如果不提供输出文件格式,默认的输出文件格式是binNASM 在缺省状态下是一个两遍的汇编器。mov ax,es:[di]是错误的,mov ax,[es:di]是正确的。mov word [var],2是正确的。mov eax,[ebx*2+ecx+offset]正确NASM 使用跟 MASM 不同的浮..原创 2021-02-06 23:06:34 · 535 阅读 · 0 评论 -
NOS 之 地址问题,堆栈SP
首先,此操作系统不叫MyOS了,叫NOS然后这个系统是分页了的,但是并没有什么问题啊,本质上加上段起始地址,映射成分页地址,但是段起始地址为0,分页地址根本没变,因此你就想象成根本没有任何地址机制就可以了。函数是如何运行的呢?到那个地方call,当前地址被压入栈,返回时从栈中弹出,就是如此,如果你在之前压入参数,那么就有可能被函数地址覆盖。SS是栈地址,我在这里其他段是第二个GDT的,然后代码段是第三个GDT!为什么要这么做?首先呢,2800000是代码起始地址,因为所有标签都是从0开始计数原创 2021-02-03 22:17:12 · 183 阅读 · 0 评论 -
MyOS 之 切换用户进程
MyOS与真正操作系统相比,就是它没有编译器(正在制作中),无法在系统里制作自己的应用级程序,但是我们仍要实现用户级应用程序的话,那么就需要在内核中自带(因为连硬盘都没有。。。),在内核中开辟一块区域用来模拟硬盘,然后开辟用户级内存,然后跳转之。存在哪里呢?存在app.asm,并入到main.asm中,就是如此。如果进行复制的话,那么这个app就不能使用任何操作系统的函数,只能使用各种门来调用系统调用。开辟用户级程序,有以下步骤:1. 开辟一块4K内存,制作一个TSS,填入GDT这个TSS地址。原创 2020-10-11 14:01:50 · 528 阅读 · 0 评论 -
MyOS 之 内存管理
检查内存呢,方法是写入内存并立刻读取,如果读取出来的数据相同则证明有内存,首先要关掉缓存,否则永远都读出正确的了。386和486的缓存是不一样的。检查内存会特别慢,原创 2020-08-17 17:42:13 · 541 阅读 · 0 评论 -
MyOS 之 文件管理
文件管理与内存管理的问题类似,碎片。无论如何也无法拒绝碎片的。理论模型,每一个文件夹模型(mk命令或者右键菜单新建的)都会有创建日期,整体是一棵树。是链表模型。但磁盘是数组模型。链表存入数组。。。要么以空间换时间,真正优的算法是不存在的。...原创 2020-09-14 18:30:41 · 343 阅读 · 0 评论 -
MyOS 之 调度与特权级
区分出特权级才能区分出用户程序,否则都是内核程序有什么用。。。现在定义超过4MB的进程都是用户级进程。现在都是在4MB内核级内,没有用也没必要实现对吧,必须有用,比如左边命令行与右边的文件显示器,一开始就是初始化成这样的,当然,都是内核级进程。文件管理,其实一开始就提到了,在ipl的时候,我们曾一个扇区一个扇区地往内存中拷贝,就是这样的,如果有文件管理功能,我们就要设计文件系统。...原创 2020-09-14 17:27:19 · 159 阅读 · 0 评论 -
MyOS 之 多任务
在一般操作系统中,切换的动作为0.01~0.03秒就会执行一次,本身切换会占用0.0001秒左右。基本上会占据1%的算力。切换时,将当前寄存器等所有上下文保存起来,读取下一个上下文,就完成了一次切换。关键就是在于TSS。TSS(任务状态段)是由程序员来提供,CPU进行维护。程序员提供是指需要我们定义一个结构体,里面存放任务要用的寄存器数据。CPU维护是指切换任务时,CPU会自动把旧任务的数据存放的结构体变量中,然后将新任务的TSS数据加载到相应的寄存器中,也就是说,在硬件上就提供了这种进程转换的能力原创 2020-08-20 10:34:00 · 289 阅读 · 0 评论 -
MyOS 之 分页
实现分页要做以下三件事:在内存某位置写好页表 页目录地址赋值给cr3 寄存器 将 cr0 寄存器的pg位置 1我们可以类比段的转化,我们最初给的地址是段选择子:段内偏移值,在保护模式下,用段选择子去内存中的段描述符表中,找到段描述符,取出段基址,再+段内偏移地址,得到最终的物理地址。页的转化也是类似的,上一步通过段描述符得到的“物理地址”,再开启分页后叫做逻辑地址。这个逻辑地址也是分成前半部分:后半部分这种形式,用前半部分的值在页表中寻找并换出一个页地址(也可以理解成基址这个概念)...原创 2020-08-28 09:38:57 · 205 阅读 · 0 评论 -
MyOS 之 图层叠加
用图层的方法,一次画上所有的图层。然后一个图层管理器,上面包含了所有的图层,每个循环画一遍图层,从头遍历,每到相应的图层就调用该进程的绘制方法,因此所有图层绘制方法都是回调函数,点击时就顺着图层管理器向下找出相应的图层,根据点击情况来进行图层的管理,但最好还是有必要时刷新,没必要就不要刷新了。而且重绘太多,会很卡。最好采用双层显存方法,所有的操作都在内置显存中,然后将内置显存刷给显存好了。提高分辨率好说啦,只不过现在意义不大。现在就可以开始多进程测试了。...原创 2020-08-22 23:09:36 · 100 阅读 · 0 评论 -
MyOS 之 定时器
定时器每隔一段时间(0.01秒)就发送一个中断信号给CPU。这其实是一个中断。要使用定时器,需要设置PIT(Programmable Interval Timer)可编程的间隔型定时器,设定PIT可以设定定时器每隔多少秒就产生一次中盾。它连着IRQ0,只要设定了PIT就可以设定IRQ0的中断间隔。现在已经和PIC一样被集成到别的芯片里了。电脑里用的定时器是8254芯片。设定3次OUT指令就可以了。mov al, 0x34out 0x43, almov al, 中断周期低8位out 0x40, a原创 2020-08-20 11:04:19 · 181 阅读 · 0 评论 -
MyOS 之 鼠标移动
图层叠加就是用于鼠标,窗口等拖动设计。原创 2020-08-20 10:34:15 · 185 阅读 · 0 评论 -
MyOS 之 Font
现在简单多了。先实现输出数字,然后看看字符串怎么样。现在遇到一个问题,就是读text段的位置怎么办?必须再加上0x280000才行。现在并没有用到任何内存,因此栈必须仔细规划一下。做的差不多了,接下来就不是一次性跑完,然后halt,而是一直在循环。计算机不再休息。响应也挺正常的,不会死机。但CPU直接拉满,到99%。halt会使CPU变成0.对于FIFO来说,根本是没办法的事情了,你必须自己去规定一个内存,因此先做完内存分配比较好。每日小常识:hlt指令1,使程序..原创 2020-08-17 17:37:50 · 128 阅读 · 0 评论 -
MyOS 之 键盘鼠标
PS/2键盘的数据端口是0x60,直接读取这个端口就能取到数据.但是前提是,键盘必须处于可读状态.在驱动中没有对端口的读取进行限制,直接汇编指令就可以读取.每次只能读取1字节.在初始化鼠标之前,必须要初始化键盘,先往0x64里写一个0x60,好像是什么写模式,然后向0x60里写入0x47,就完成了。如何确定键盘可读呢?答案是读取键盘的命令端口.如果读出的值没有0x02标记,则说明可以读取.等待到可以读取的代码如下:waitkbdout: IN AL,0x64...原创 2020-08-17 14:11:01 · 528 阅读 · 0 评论 -
MyOS 之 PIC
中断请求(IRQ,中断信号,理解为中断控制器的端口,虽然PIC一般只有8个端口,但是可以串联,然后就16位了)中断控制器(PIC)一般中断信号就16个(你注意下面第2号IRQ代表什么),与CPU直接相连的叫主PIC,负责0~7号中断,从PIC负责8~15号中断,从PIC通过第2(从0开始)号IRQ与主PIC相连,硬件设定就是这样的。PIC的中断向量IRQ编号 设备名称 用途IRQ0 Tine 计算机系统计时器IR...原创 2020-08-15 14:15:57 · 288 阅读 · 0 评论 -
MyOS 之 GDT,IDT
貌似GDT有8192个,最好是看他大致思路,然后自己总结过程。现在仍要好好设计一下内存结构:0~0xffffffff(共8位,4G)。0x7c00之前是BIOS,引导完了就没用了。0x8200(33kb处)之后是不超过1MB的代码段。0x280000(2.6MB处)是真正的代码段开始。GDT从0x270000处开始。GDT一行8字节,一共8192行,一共65536字节=65KB。1KB,正好是0x10000.IDT从0x26f800处开始。IDT一行也是8字节,一共256行,一共原创 2020-08-13 17:09:12 · 252 阅读 · 0 评论 -
MyOS 之 转入32位,变量名设计
打算转入的单独放一次,main跟其他所有文件%include一下,boot文件与main文件也是按顺序来的。按顺序来的话,每个文件都要设定好偏移。这种顺序填入的并不用担心标签重复的问题,但是%include需要担心,因此这里采用namespace。所有的在外部引用的函数都加上文件名前缀!根据include的顺序在文件名前加上序号。这样就可以每个文件引用序号小的,不允许引用序号大的。因此也应该在最开始设定好序号。0_xxx是常量定义区1_xxx是变量定义区2_xxx是函数定义区,但不会调用别的原创 2020-08-06 17:49:30 · 148 阅读 · 0 评论 -
MyOS 之 汇编链接
需要重新设计makefile了。ipl是默认装载到0x7c00的,只装这512字节的。然后我们将整个1.44MB装到0x0820开始的地方。感觉两个文件的链接并不是简单链接。首先每个文件都必须加偏移,也就是org。不知道,可能给寄存器就必须少一个0吧。。。因为现在还在16进制,遵循加10加指针的形式。然后实现两个汇编文件的链接实现,而不是上下关系。第一种是用%include "func.asm",这个与C语言文件完全相同,就是拷贝过来。怎么说呢,这么做特别容易造成标签污染。那么现原创 2020-08-06 16:26:53 · 137 阅读 · 0 评论 -
MyOS 之 汇编化
其实后面连接也没关系,根本不用管。现在的确是需要进行系统化命名了。现在实现再添加一个asm文件取代C语言文件。新创建一个main.nas文件,文件里只是:main: HLT ; 让CPU停止,等待指令 JMP main ; 无限循环最简单的系统。编入makefile。成功,然后与汇编函数文件联动。不行,太乱了,引用的文件太多,根本不知道什么是什么。还是自己实现所有文件吧。...原创 2020-08-05 13:16:18 · 212 阅读 · 1 评论 -
MyOS 之 软盘读取
首先还是采用软盘启动,qemu实现,把30DayOS的第一天版复制进去即可。这里我选择的是第4天,此时已经构建完毕所有页面了,我需要用nasm汇编重构即可。软盘的大小的组织方式:80cylindersx2headsx18sectorsx512bytesCHS,是FDISK在分区期间所需磁盘信息。CHS寻址模式将硬盘划分为磁头(Heads)、柱面(Cylinder)、扇区(Sector)。△磁头(Heads):每张磁片的正反两面各有一个磁头,一个磁头对应一张磁片的一个面。因此,...原创 2020-08-05 11:30:47 · 809 阅读 · 0 评论 -
MyOS 之 立项,目录
现在开始重新写了,之前依赖的东西太多,导致一直兼容报错,或者一直用别人的东西,独立性越来越差。因此这次我用nasm汇编来做!整体还是仿照30DayOS来设计,然后工作还是在WinXP虚拟机上。另外文档就全在网上写了,不在readme.md上写,md文档上只记录一下进度就好了。操作系统特性:首先,定义变量var:1.s:Txt.arr:{1,2,3}.a:arr\1.dict:{2:23,"4":4,"hi":"hello"}.a<-dict\"...原创 2020-08-05 10:49:26 · 148 阅读 · 0 评论 -
nachos操作系统(八)
那么你就要知道,如何在一个程序里面运行下一个程序,完成之后还能回到这个程序?就对于linux系统而言,它还是多进行 ,肯定 是linux永远执行的,其他程序依次调用进cpu,cpu肯定只有一个,它调用一个程序,那么linux系统此时肯定不执行,难道就是说,一旦某一个程序在cpu里面卡住,它还能不执行了不成?因此,从这个角度来看,linux与其他进程无异,就是其他程序 运行完毕后,调用中断给li...原创 2019-12-27 11:47:46 · 500 阅读 · 0 评论 -
nachos操作系统(七)
本节实现重新写内存分配管理。主要有两个知识点,一个是内存管理,一个是系统调用,现在先实现内存管理,然后实现系统调用,预计至多4个课时。预计内存管理就是写比较简单的,系统调用都是这样预见的。要实现内存管理,就要实现多道程序并行运行,不然内存管理没法测试,因此要先实现Exec。userprog/syscall.h里面写的系统调用号为:/* system call codes -- used...原创 2019-12-20 11:18:05 · 391 阅读 · 0 评论 -
nachos操作系统(六)
今天完成两个demo,完成了就整个实验部分完结了,就可以写实验报告了。现在实现新建一个缓冲区,然后开几个线程,然后实现读取,但是问题是,这个线程也是线性的,你没有办法把它,emmm,挂起来,而且是缓冲区自动实现的锁,这个锁,就当无所不能来用,任何时候挂起都没有关系,那么就是先写入,然后挂起,然后读出好了。现在是偶数个挂起,但是它们存还是按顺序存的,9永远在之外,它总是会出现一个0,这个0可能是...原创 2019-11-15 11:11:00 · 138 阅读 · 0 评论 -
nachos操作系统(五)
实际上,如果实现锁机制还是条件变量什么的,双向链表的线程切换其实根本就是不用管的,只要我们锁机制实现的好,管它怎么切换呢。在哪里上锁呢,是在DLListThread,可以把insert和remove看成管程方法,然后在里面实现锁机制就不错。实现锁之后,就是简单的引用就可以了,需要注意的是,之前造好的makefile需要进行改正,不同的实验需要不同的makefile,因此,需要将系统多次备份。这...原创 2019-11-12 22:57:29 · 165 阅读 · 0 评论 -
nachos操作系统(四)
今天用锁+条件变量实现互斥。但是怎么用呢?重新说明一下,当系统开始运行后,它首先执行thread中的main函数,然后,main函数第一个参数是一个数字,第二个参数是一个字符串,二维的不知道是为什么。q是设置testnum,测试哪个函数t是设置threadnum(线程数),n就是设置n(节点个数),e是设置err_type(错误类型),有一个default,还是设置testnum。...原创 2019-11-08 11:03:44 · 493 阅读 · 0 评论 -
nachos操作系统(三)
今天将nachos中的锁机制和条件变量的实现补充完整,并利用这些同步机制实现几个基础工具类。1. 实现锁机制和条件变量,并利用这些同步机制将实验一中所实现双向有序链表类修改成线程安全的;2. 实现一个线程安全的表结构;3. 实现一个大小受限的缓冲区。在synch.h中,有semaphore类,即信号类,里面封装了PV操作,还有value和queue等基本东西,Lock类,这个类里面的东西比...原创 2019-11-01 20:03:43 · 500 阅读 · 0 评论 -
nachos操作系统(二)
今天继续深入这个系统。首先,在main.cc中,主要就是这个处理参数,其中,q是设置testnum,t是设置threadnum(线程数),n就是设置n(节点个数),e是设置err_type(错误类型),有一个default,还是设置testnum。然后就进入了threadtest函数。在threadtest.cc中,就是主要功能了,它说设置测试号为2,意思是里面加了不少自己编写的函数,例如D...原创 2019-10-20 11:22:00 · 288 阅读 · 0 评论 -
nachos操作系统(一)
今天来了解一下整个系统的构成。nachos-3.4下有一个C++例子文件夹和一个code文件夹,code文件夹下才是程序的源码,总文件夹下的makefile呢,就是进入各个子文件夹,make他们自己的makefile,先执行depend,也就是依赖,依赖是很复杂的,然后才是编译本体,至于本体是什么,下面再讲,然后就是一个移除过程文件,注意对于makefile,一般是以第一个标签为生成对象,剩下的...原创 2019-10-12 00:09:04 · 890 阅读 · 0 评论 -
自制IDE
我的IDE目前就是这个样子(从知乎上迁移过来的…………):这货可谓承载了我所有对IDE的幻想(毕竟是自己亲手调教的嘛),在讲这个IDE之前,让我先说说我为什么要自己设计一个IDE。我在上大学之前就会编程,上大学之后,老师推荐的是codeblocks,私底下有些同学自己下Visual studio,或者Dev C++之类的,我也全试过,但是我发现一个问题:颜值高的IDE占用内存大(像Vis...原创 2019-10-11 14:31:21 · 3148 阅读 · 2 评论 -
自制操作系统(七)
那么,我这个操作系统有什么优点呢?首先呢,所有代码我必须自己掌控对吧,代码用的谁的无所谓了。它的ui可以是全平台的。windows是最好的系统。它的ui无可挑剔。我的更新是它可以自适应。右上角是各种信息,当程序最大化时可以缩到标题栏。因为最大化往往只有一个对吧。应用商店嵌套在应用菜单里,太棒了。就这样。然后桌面放文档,你可以一直将应用菜单开着啊,就这么愉快的决定了!那么操作系统重新开...原创 2020-02-02 09:17:38 · 222 阅读 · 0 评论 -
自制操作系统(六)
今天来解决一下历史遗留问题。首先,文件名全部按照小写字母表示,用C语言写的,为什么不用C++?那是因为C++有可能在编译过程中将main函数改名,这个很难办。然后,尽可能的套娃,这样include进去的也少。即便有测试的,也要用一个test函数解决问题。这个文件的组织也是一个大问题。。。参考Linux,我是这么组织文件的。document // 源码解释文档文件夹video // 显示相...原创 2020-02-01 17:49:51 · 182 阅读 · 0 评论 -
自制操作系统(五)
这一节要实现中断。 中断是有固定格式的,要顺应着CPU来,格式如下:typedef struct SEGMENT_DESCRIPTOR{ short limit_low, base_low; char base_mid, access_right; char limit_high, base_high;} SegmentDescriptor;...原创 2019-09-30 10:35:51 · 147 阅读 · 0 评论