
从零开始写一个简单操作系统阅读笔记
whime_sakura
分享记录一些学习笔记,写的很不好的请见谅。
展开
-
操作系统的引导区块
pdf地址:https://pan.baidu.com/s/1ix6rDfE4rLxazcwwKPlbNQ,仅供学习之用。 按照上图使用二进制编辑器BZ写一个512字节的引导区块,中间* 为省略的零,做成VMware镜像,然后开启虚拟机,但是出现operating system not found的情况:代码说明如下:这里的magic number(幻数)为0x aa...原创 2018-10-31 10:08:55 · 435 阅读 · 0 评论 -
基本屏幕驱动实现
实现一个新的驱动实现文件screen.c和一个驱动接口文件screen.h,实现屏幕输出功能,代替C语言printf函数。(不知道为啥做这个)在头文件中定义一些端口常数: screen.c: 在计算screen_offset时,offset=(row*80+col)*2,使用以下端口访问方式写入offset。 获得光标位置:使用特殊的...原创 2018-10-30 10:32:11 · 2257 阅读 · 0 评论 -
硬件IO
对于显示器工作原理的解释 使用in,out指令读写设备控制器的寄存器。行内汇编原创 2018-10-30 10:32:33 · 422 阅读 · 0 评论 -
组织操作系统代码库
通过使用make变量和wildcard的方法避免单独地对单个文件进行编译。 也可以使用如下方法减少重复代码的编写。原创 2018-10-30 10:33:01 · 152 阅读 · 0 评论 -
执行我们的内核代码
本小节将分为以下步骤先写一个简单的内核,只显示一个字符。创建一个加载内核的引导区 可以使用如下代码将引导区和内核代码连接成一个内核镜像。源代码如下: 如何进入内核 为了防止进入内核执行时的首条指令不是main函数的,比如这样子的程序,执行时将不会执行到main函数。为此增加一个内核入口函数:kernel_entry.nas之后将...原创 2018-10-30 10:33:16 · 552 阅读 · 0 评论 -
局部变量
使用如下代码声明一个int类型的局部变量。反汇编结果为:(eax存储返回值)这里有两个注意的点:Sub esp,byte + 0x10 首先堆栈使用时的地址是逐渐递减的,使用esp 减去0x10,即减去16字节,是因为编译器处理堆栈时进行了优化,减少低效的处理大量的内存边界(?)和数据类型倍数不一致(对齐?)的情况。通过浪费一些内存,为每一个栈元素分配最大数据类型...原创 2018-10-30 10:33:36 · 381 阅读 · 0 评论 -
了解C的编译
使用反汇编器可以对目标文件进行反汇编,可得到类似下面的汇编文件: 从左至右依次是指令在文件中的偏移地址,机器码,对应的汇编指令。 当发生函数调用时,C语言会先将原栈底ebp入栈。在原有堆栈上面建立一个空栈,这个叫做建立栈帧,用于分配所有的局部变量。使用eax来传递返回值。...原创 2018-10-30 10:33:49 · 150 阅读 · 0 评论 -
从16位实地址模式转换到32位保护模式的引导区程序
根据之前的几个程序,可以写出一个从16位实地址模式转换到32位保护模式的引导区程序。原创 2018-10-30 10:34:20 · 353 阅读 · 0 评论 -
从16位实模式切换到32位保护模式
通过设置一个特殊的CPU控制寄存器的首位开启32位保护模式。 为了使所有的指令在切换前全部执行完毕,可以通过段远程调用迫使CPU完成管道流水中不同状态的指令。 jmp <segment>: < address offset > 整个切换过程可以如下: ...原创 2018-10-30 10:34:47 · 1300 阅读 · 1 评论 -
使用汇编描述GDT
使用6个字节的gdt descriptor记录GDT的地址和大小。复杂的设置:原创 2018-10-31 10:05:57 · 924 阅读 · 2 评论 -
GDT-全局描述符表
32位保护模式下段寄存器保存的是GDT表项的索引。 GDT的入口8个字节是一个无效的空描述符,以防止我们在寻址前错误的设置段寄存器为0x0,这时候CPU会抛出一个异常,实际上是一个中断。 GDT结构: ...原创 2018-10-31 10:06:12 · 798 阅读 · 0 评论 -
使用VGA显示字符串
32位保护模式提供了更大的内存寻址空间,cpu执行速度,更好的内存保护机制。 将CPU从16位切换到32位需要一个复杂的数据结构,全局描述符表GDT, 其中定义了内存分段和它们的保护模式属性。我们使用一个特殊的指令加载之后,再对CPU的一个特殊的控制寄存器设置单独的一个位来进行转换。 直接写string进video memory。 ...原创 2018-10-31 10:06:56 · 1712 阅读 · 0 评论 -
使用BIOS读磁盘
16位实模式中使用段地址:偏移地址寻址的方式扩大内存寻址空间。调用BIOS 0x13号中断可以读写磁盘到指定内存位置。al保存读写的扇区数,dl保存磁盘号,ah=0x02表示读函数,ch保存柱面号,dh保存磁头号(0,1),cl保存起始扇区号(从1开始编号)。读取的数据保存在es:bx所指的数据中。 BIOS通过设置IF标志位为1,al为实际读取的扇区号,检查是否...原创 2018-10-31 10:07:11 · 1714 阅读 · 0 评论 -
声明字符串,堆栈,函数调用
声明字符串并使用0 标识字符串长度。 在函数调用前,可以使用CPU实现的两个指令pusha和popa保存所有寄存器值。原创 2018-10-31 10:07:24 · 213 阅读 · 0 评论 -
打印字符
调用BIOS 0x10号中断打印字符,ah设置为0x 0e,表示tele-type模式,al 为需要打印的字符。对应的机器码: 为了不破乱存放在0x00内存地址的中断向量表,BIOS经常将引导分区存放在内存地址0x7c00中。 ...原创 2018-10-31 10:07:41 · 2437 阅读 · 0 评论 -
16位实模式
Intel 8086 CPU采用的是16位实模式,没有内存保护的概念。之后随着CPU的发展,为了兼容16位机器和系统,所有的系统都是从16位模式开始引导,采用32/64位的CPU的机器需要从16位切换到32/64位模式。 想要在屏幕上输出信息,必须知道屏幕的接口,为此可以调用BIOS函数帮助我们完成这一任务。不过不同机器的BIOS例程的差异可能会导致错误。所以可以借助...原创 2018-10-31 10:07:58 · 782 阅读 · 0 评论 -
再谈引导区
这次我们使用汇编语言创建引导区,我们可以使用以下命令将汇编语言源程序汇编成机器语言源程序-f bin 意味着生成单纯的机器码文件而不是经过链接的文件,因为现在还不需要。在汇编程序文件里面,在幻数0x aa55之前填充510个字节0x 00,生成512个字节的文件。可以使用以下方式进行引导使用以下命令可以查看二进制文件包含的内容: ...原创 2018-10-31 10:08:10 · 254 阅读 · 0 评论 -
结构体的使用和显示模式的保存
使用结构体这部分主要是对asmhead.nas保存下来的状态信息读出,在bootpack.c里面使用。将0x0ff0即VRAM地址使用结构体指针存放,按照结构体存储,注意对应的结构体声明顺序应该与汇编语言里的顺序一致。(个人理解) 显示字符 要显示字符,可以用8X16长方形像素点阵表示,像如下转换: 只需要根据对应的字体0...原创 2018-10-29 00:52:25 · 228 阅读 · 0 评论