
操作系统实战45讲
zhaoseaside
树立个人IP,探索副业可能
展开
-
Ubuntu 18.04使用Qemu和GDB搭建运行内核的环境
是官网。下载源代码。解压源文件。进入源代码目录里边。执行使用使用删除,然后再使用安装make,发现正常安装。安装依赖包。进行配置。使用上下键可以选择,选择“Setting”之后,按回车键。进入到下一个选择时,使用上下键找一下“然后按一下就是选择上了。按一下键就可以退回到上一层。按一下键就可以退回到保存界面。选择“yes”按一下键,就退到原来的命令行下。进行编译。进行安装。原创 2023-12-09 22:24:57 · 1937 阅读 · 1 评论 -
64位intel汇编语言使用数组计算三位数的和
jnz,是“jump if not zero, or not equal”的缩写,这个指令会判断rflags中零标志。若是为不为零的话,则跳转到。此文章为3月Day 18学习笔记,内容来源于极客时间。若是为零就会执行这个指令下边的指令。原创 2023-03-18 23:18:00 · 198 阅读 · 0 评论 -
64位intel汇编语言选出数组最大值
以前写的许多汇编代码都是在别人可运行的完整代码上更改,今天我从头开始写了基于数组选择最大值的汇编代码,写汇编代码渐入佳境。汇编语言中的执行流就相当于C语言中函数,C++语言中的方法。用来记录每次比较时数组每一个元素的位置,在计算机中,变量名代表内存地址。用来记录数组中每一次比较之后的最大值,刚开始的时候初始化为0,第三步,考虑如何使用寄存器保存初始化的值,使用。注意上边代码只是帮助理解,在上边C语言中定义的。都会放到内存中,而不是真的放到对应的寄存器中。第四步就是写比较数组的代码,主体代码放到了。原创 2023-03-19 23:37:52 · 474 阅读 · 0 评论 -
32位intel汇编语言使用数组计算三个数的和
此文章为3月Day 16学习笔记,内容来源于极客时间。把上边代码存成sumDB.asm文件。原创 2023-03-16 23:42:01 · 163 阅读 · 0 评论 -
实模式下内存代码演示
此文章为4月Day 29学习笔记,内容来源于极客时间。原创 2023-04-29 23:35:28 · 78 阅读 · 0 评论 -
切换到保护模式
接下来,CPU 发现了 CRO 寄存器第 0 位的值是 1,就会按 GDTR 的指示找到全局描述符表,然后根据索引值 8,把新的段描述符信息加载到 CS 影子寄存器,当然这里的前提是进行一系列合法的检查。无法直接或间接 mov 一个数据到 CS 寄存器中,因为刚刚开启保护模式时,CS 的影子寄存器还是实模式下的值,所以需要告诉 CPU 加载新的段信息。第二步,加载设置 GDTR 寄存器,使之指向全局段描述符表。第四步,进行长跳转,加载 CS 段寄存器,即段选择子。第一步,准备全局段描述符表,代码如下。原创 2023-04-28 23:43:16 · 88 阅读 · 0 评论 -
保护模式中断
在实模式下,可以在不用判断权限获取中断号,CPU就能根据 IDTR 寄存器中的信息,计算出中断向量中的条目,进而装载 CS(装入代码段基地址)、IP(装入代码段内偏移)寄存器,最终响应中断。而保护模式下的中断要权限检查,还有特权级的切换,所以就需要扩展中断向量表的信息,即每个中断用一个中断门描述符来表示,也可以简称为中断门,中断门描述符依然有自己的格式,如下图所示。此文章为4月Day 27学习笔记,内容来源于极客时间。原创 2023-04-27 22:34:57 · 175 阅读 · 0 评论 -
保护模式平坦模型
32 位的CPU寄存器最多只能产生 4GB 大小的地址,而一个段长度也只能是 4GB,所以我们把所有段的基地址设为 0,段的长度设为 0xFFFFF,段长度的粒度设为 4KB,这样所有的段都指向同一个((段的长度 +1)* 粒度 - 1)字节大小的地址空间。x86 CPU并不能直接使用分页模式,需要在分段模式的前提下,看实际情况再决定是否开启分页。这源自硬件的规定,程序员只能遵守,可以简化设计,使分段成为“虚设”,这就是保护模式的平坦模式。分段模式有很多缺陷,现代操作系统一般都是使用分页模式。原创 2023-04-26 22:40:14 · 183 阅读 · 0 评论 -
保护模式段选择子
通常情况下,CS 和 SS 中 RPL 就组成了 CPL(当前权限级别),所以常常是 RPL=CPL,进而 CPL 就表示发起访问者要以什么权限去访问目标段,当 CPL 大于目标段 DPL 时,则 CPU 禁止访问,只有 CPL 小于等于目标段 DPL 时才能访问。上图中影子寄存器是靠硬件来操作的,这样就对对系统程序员不可见,是硬件为了减少性能损耗而设计的一个段描述符的高速缓存,不然每次内存访问都要去内存中查表,那性能损失是巨大的,影子寄存器也正好是 64 位,里面存放了 8 字节段描述符数据。原创 2023-04-25 22:47:08 · 109 阅读 · 0 评论 -
保护模式段描述符
由于CPU的扩展导致了32位的段基地址和段内偏移,所以16位的段寄存器就无法放下这些信息。可以看出段寄存器中不再存放段基地址,而是具体段描述符的索引,访问一个内存地址时,段寄存器中的索引首先会结合 GDTR 寄存器找到内存中的段描述符,再根据其中的段信息判断能不能访问成功。段描述符有64位(8字节)数据,里面包含了段基地址、段长度、段权限、段类型(可以是系统段、代码段、数据段)、段是否可读写,可执行等。多个段描述符在内存中形成全局段描述符表,该表的基地址和长度由 CPU的GDTR 寄存器指示。原创 2023-04-24 23:01:33 · 341 阅读 · 0 评论 -
保护模式特权级
为了区分那些指令可以执行和哪些资源可以访问,CPU实现了特权级。特权级分为4类,R0至R4,每个特权级可以执行的指令数量不同。正如下图所示,R0可以执行所有指令集,而后边的R1至R3,可以执行的指令集数量依次减少。而内存的访问则需要靠指令集和特权级相互配合来实现。上面的圆环图,从外到内,既能体现权力的大小,又能体现各特权级对资源控制访问的多少,还能体现各特权级之间的包含关系。R0 拥有最大权力,可以访问低特权级的资源,反之则不行。此文章为4月Day 23学习笔记,内容来源于极客时间。原创 2023-04-23 15:20:41 · 163 阅读 · 0 评论 -
保护模式浅析
虽然 CPU 内部器件的位数解决计算和寻址问题了,但仍然没有解决前面那个实模式场景下的问题,导致前面场景出问题的原因有两点:(1)CPU对指令不加区别地执行;(2)CPU对访问内存的地址不加限制。随着时间的发展,内存变得大了,那么首先需要解决的就是寻址问题,CPU的寄存器和运算单元位数都变成了32位。所有的寄存器都扩充到32位,还可以单独使用低16位,这个低16位又可以拆分成两个8位寄存器。此文章为4月Day 22学习笔记,内容来源于极客时间。原创 2023-04-22 21:42:40 · 112 阅读 · 0 评论 -
实模式中断
有了中断号以后,CPU 就能根据 IDTR 寄存器中的信息,计算出中断向量中的条目,进而装载 CS(装入代码段基地址)、IP(装入代码段内偏移)寄存器,最终响应中断。硬件中断是指中断控制器给CPU发送了一个电子信号,CPU会对这个信号进行应答,之后中断控制器会将中断号发送给CPU。中断实现离不开特定的寄存器—IDTR指向内存中的中断向量表,这个中断向量表的一个条目由代码段地址和段内偏移组成。软件中断就是CPU执行了INT 指令,这个指令后边会跟着一个常数,这个常数就是软中断号。原创 2023-04-21 15:20:56 · 204 阅读 · 0 评论 -
16位MASM汇编语言编译执行
这是16位MASM汇编语言,就是在屏幕上输入“Hello World!”,我这里使用DOSBox 0.74-3进行模拟,使用16位MASM.EXE进行汇编,使用16位LINK.EXE进行汇编。进入到虚拟d:\asm目录下,实际上相当于进入e:\dos\asm目录下。进入虚拟d盘中,就是相当于进入电脑中真实e:\dos目录下。此文章为4月Day 19学习笔记,内容来源于极客时间。将笔记本电脑中e:\dos挂载在虚拟d盘上。设置路径,就相当于在Linux中。原创 2023-04-20 23:09:52 · 443 阅读 · 0 评论 -
实模式下内存访问
所有的内存访问都需要段寄存器左移四位加上其他寄存器的值才能得到真正地址值。这是由于以前运行实模式的8086处理器,有20位地址线,可以取到1MB地址。这里解释一下,为什么是B而不是bits。虽然有了寄存器,但是数据和指令还是需要存储到内存中。通常情况下需要把数据从内存中放到寄存器中才能使用,同样的指令需要放到寄存器中才能被CPU执行。内存中是按字节来组织的,单次访问的最小单位就是1字节,即1B(Byte)。此文章为4月Day 19学习笔记,内容来源于极客时间。所以若是地址线有1根的话,就能取到2B地址。原创 2023-04-19 22:43:17 · 329 阅读 · 0 评论 -
实模式的寄存器
AF: auxiliary carry flag,辅助进位标志,运算时,第3位向第4位产生进位时为1,否则为0.PF: parity flag,奇偶标志,运算结果操作数位为1的个数为偶数个时为1,否则为0.OF:overflow flag,溢出标志,操作数超出机器能表示的范围表示溢出,溢出时为1。CF: carry flag,进位标志,最高有效位产生进位时为1,否则为0.ZF: zero flag,零标志,运算结果等于0时为1,否则为0.TF: trap flag,陷阱标志,用于调试单步操作.原创 2023-04-18 22:02:28 · 684 阅读 · 0 评论 -
CPU实模式
实模式又被称为实地址模式,实,就是真实的意思,需要分为两方面看,一个方面就是运行真实的指令,对动作的指令不做区分,直接执行指令的真实功能,另一方面发往指令的地址是真实的,对任何地址不限制地发往内存。因为操作系统直接运行在硬件之上,所以操作系统开发者需要学习一些硬件知识。而在硬件中,最重要的就是CPU,它是执行程序的核心硬件。我们常使用的是X86架构,所以需要增强对X86 CPU的理解。此文章为4月Day 17学习笔记,内容来源于极客时间。原创 2023-04-17 21:52:09 · 153 阅读 · 0 评论 -
Windows NT 内核浅析
所有的设备驱动和文件系统都由 I/O 管理器统一管理,驱动程序可以堆叠形成 I/O 驱动栈,功能请求被封装成 I/O 包,在栈中一层层流动处理。Windows 引以为傲的图形子系统也在内核中。现代Windows系统的内核就是 NT,Windows NT 是微软于 1993 年推出的面向工作站、网络服务器和大型计算机的网络操作系统,也可作为 PC 操作系统。它是一款全新从零开始开发的操作系统,应用了现代硬件的所有特性,“NT”是“New Technology”的缩写,也就是“新技术”的意思。原创 2023-04-16 22:47:54 · 1685 阅读 · 0 评论 -
Darwin-XNU 内核架构浅析
苹果公司的产品有平板、手机、计算机和笔记本,手机和平板使用的是iOS,而计算机和笔记本使用的是macOS。Mach 内核是卡耐基梅隆大学开发的经典微内核,意在提供最基本的操作系统服务,从而达到高性能、安全、可扩展的目的,而 BSD 则是伯克利大学开发的类 UNIX 操作系统,提供一整套操作系统服务。应用会通过用户层的框架和库来请求 Darwin 系统的服务,即调用 Darwin 系统 API,这时会传入一个API号,若是API号小于0,调用的是Mach层,若是API号大于0,调用的是BSD层。原创 2023-04-15 21:23:12 · 1396 阅读 · 0 评论 -
Linux内核浅析
上图仍然没有展现Linux所有,只是展示五大组件,即:系统(System)、进程(Processing)、内存(Memory)、存储(Storage)和网络(Network)。Linux,全称为GNU/Linux,支持类Unix、POSIX标准接口,支持多用户、多进程、多线程,可以在多CPU计算机运行,让所有人免费使用和自由传播。Linux的基本思想就是一切皆是文件,每个文件都有它的特殊作用,包括用户数据、命令、配置参数都可以看做文件。此文章为4月Day 14学习笔记,内容来源于极客时间。原创 2023-04-14 21:57:56 · 92 阅读 · 0 评论 -
自制操作系统内核的层次
(2)检查其参数是否合法,如果参数有问题就返回相关的错误,若是参数正确接着调用下层完成功能核心代码。(1)定义一套UNIX接口的子集,只需要几个接口就可以大致定义出操作系统的功能。此文章为4月Day 13学习笔记,内容来源于极客时间。(5)平台其它相关的功能。(2)CPU 控制。(4)物理内存管理。原创 2023-04-13 23:07:41 · 123 阅读 · 0 评论 -
操作系统之分离硬件相关性
进程是操作系统开发者为了多任务的实现而提出的,并让每个进程在CPU上运行一小段时间,这样就能实现多任务同时运行的假象。不难发现ARM架构或者X86架构,选择一个进程的算法和代码是不易改变的,需要改变的是进程切换的代码,因为不同机器的上下文是不同的。分离硬件的相关性,就是把操作硬件和处理硬件功能差异的代码抽离出来,形成软件抽象层,对外提供相应的接口,方便上层开发。2.进程切换,就是停止当前进程,运行新的进程,主要动作是保存当前进程的机器上下文,装载新进程的机器上下文。屏蔽底层细节,使上层开发更简单。原创 2023-04-12 22:37:18 · 609 阅读 · 0 评论 -
操作系统之微内核架构
与宏内核相反,微内核架构提倡功能尽可能少,只提供进程调度、处理中断、内存映射、进程间通信等功能。微内核架构是不能够提供什么实际功能的,而内存管理、进程管理、设备管理和文件管理服务等,都被做成一个个服务进程,它们和用户进程一样,只是它们能够提供宏内核里边提供的功能。微内核提供了一种良好的进程间通信机制:消息。应用程序在调用某项服务时,会向微内核发送一个消息,而由微内核再往具体的服务进程发送,接着进程就会完成具体的功能。服务进程的编程模型就是循环处理来自其他进程的消息,完成对应的功能。原创 2023-04-11 23:00:03 · 816 阅读 · 0 评论 -
操作系统之宏内核结构
这个大的文件里边有所有功能的代码,会提供一些接口给用户程序,而这些接口就是常说的系统API。而这个大的程序会在CPU特权模式下运行,这个通常称为宏内核模式。在知道了操作系统有什么组件,就需要知道如何组织这些组件,可以通过一些经典的内核来学习组织操作系统组件,这篇文章来介绍一下宏内核结构。宏,就是大,在宏内核结构里边,需要把例如进程管理、内存管理、I/O管理等组件通过编译之后链接成一个大的可执行文件。此文章为4月Day 10学习笔记,内容来源于极客时间。原创 2023-04-10 20:27:46 · 467 阅读 · 0 评论 -
操作系统内核作用
想要实现操作系统内核,就需要了解内核里边有什么。首先,我们需要明白操作系统内核就是资源的管理者,管理资源就是为了给应用更好地使用资源。计算机资源大致包括两类:硬件资源和软件资源。硬件资源包括以下七种:1.总线,负责连接各种其它设备,是其它设备工作的基础。2.CPU,即中央处理器,负责执行程序和处理数据运算。3.内存,负责储存运行时的代码和数据。4.硬盘,负责长久储存用户文件数据。5.网卡,负责计算机与计算机之间的通信。6.显卡,负责显示工作。原创 2023-04-09 20:09:11 · 982 阅读 · 0 评论 -
16位Boot直接操作显存显示白色字符和红色字符
创造一个大小为30M模式为flat的硬盘,bximage不是Linux原生程序,需要安装bochs才能使用。此文章为4月Day 8学习笔记,内容来源于极客时间《操作系统实战 45 讲》。将mbrGraphicsCard.bin写入到boot.img文件里边。生成mbrGraphicsCard.bin文件。”之后按回车键开始模拟运行。原创 2023-04-08 17:45:05 · 164 阅读 · 0 评论 -
AT&T汇编风格16位Boot引导程序
此文章为4月Day 6学习笔记,内容来源于极客时间《操作系统实战 45 讲》。将gasOsBoot.bin写入硬盘。创造一个60M模式为flat的硬盘。原创 2023-04-07 23:10:49 · 260 阅读 · 0 评论 -
使用mbr在清空之后的屏幕上显示绿色字
此文章为4月Day 6学习笔记,内容来源于极客时间《操作系统实战 45 讲》。将mbrWrite.bin写入到boot.img文件里边。将mbrWrite.asm生成bin文件。使用bochsrc文件开始模拟。创建一个60M大小的硬盘。输入“c”,按回车键。原创 2023-04-06 23:04:02 · 248 阅读 · 0 评论 -
引导程序的作用
PC 机 BIOS 固件是固化在 PC 机主板上的 ROM 芯片中的,掉电也能保存,PC 机上电后的第一条指令就是 BIOS 固件中的,它负责检测和初始化 CPU、内存及主板平台,然后加载引导设备(大概率是硬盘)中的第一个扇区数据,到 0x7c00 地址开始的内存空间,再接着跳转到 0x7c00 处执行指令。此文章为4月Day 5学习笔记,内容来源于极客时间。原创 2023-04-05 22:36:13 · 171 阅读 · 0 评论 -
解释输出“Hello OS!”汇编代码逻辑
可以实现按指定范围向上滚动窗口的功能,同时也具备清屏的功能。此文章为4月Day 4学习笔记,内容来源于极客时间。bh=滚动后空出位置放入的属性,可以设置颜色。al=滚动的列数,若为0则实现清空屏幕功能。上边的代码使用vim或者其他编辑器保存成。,基本输入输出系统)中断服务程序。ch=滚动范围的左上角坐标列号。cl=滚动范围的左上角坐标行号。dh=滚动范围的右下角坐标列号。dl=滚动范围的右下角坐标行号。来让bochs模拟,使用。原创 2023-04-04 23:26:45 · 380 阅读 · 0 评论 -
汇编语言启动程序输出“Hello OS!”
把boot.bin写入到boot.img。使用bochsrc这个文件开启bochs。保存成boot.asm文件。要是安装了qemu,可以使用。按“6”和回车键开启模拟。原创 2023-04-03 21:32:31 · 155 阅读 · 0 评论 -
操作系统45讲之Ubuntu 18.0.4使用GRUB配置并启动自己的简单操作系统雏形
其中的“sda1”就是硬盘的第一个分区(硬件分区选择 MBR),但是 GRUB 的 menuentry 中不能写 sda1,而是要写“hd0,msdos1”,这是 GRUB 的命名方式,hd0 表示第一块硬盘,结合起来就是第一块硬盘的第一个分区。发现多了不少文件,HelloOS.bin需要移动到/boot目录下。将上边写入到grub.cfg的内容写入到40_custom文件中。更新/boot/grub/grub.cfg文件。按下“ESC”可以正常退出到grub引导菜单。将下边的内容写到grub.cfg中。原创 2023-04-02 19:12:09 · 2025 阅读 · 0 评论 -
64位intel汇编代码将字符串通过堆栈的方式倒置字符串12345
此文章为4月Day 1学习笔记,内容来源于极客时间。上边的文件使用编辑保存为。原创 2023-04-01 22:50:20 · 248 阅读 · 0 评论 -
gdb堆栈相关命令
此文章为3月Day 31学习笔记,内容来源于极客时间。原创 2023-03-31 14:34:51 · 697 阅读 · 0 评论 -
gdb展示数据
显示loopTotal的值,因为断点停留“int loopTotal = 10;”前,所以loopTotal里边还是一个垃圾值,并不是10。此文章为3月Day 30学习笔记,内容来源于极客时间。再次显示loopTotal这个变量的值就是正确的。可以在每次运行到断点的时候,显示变量的值。显示出loopTotal是int类型,显示出来sum是float类型。看一下第1行到第10行代码,就在sum改变的时候显示值。显示所有设置的断点。whatis 变量名。可以看出变量的类型,进入到for循环中,原创 2023-03-30 19:01:15 · 167 阅读 · 0 评论 -
gdb学习删除断点delete/clear和断点暂停disable
就是删除所有断点的意思,输入“y”就会删除所有断点。此文章为3月Day 29学习笔记,内容来源于极客时间。就是删除第1个断点,要是删除没有的断点,就会提示。开始调试后,发现直接到了第4个断点处。暂停断点,经过断点时不停止。上边的代码使用编辑器保存成。上边的代码用编辑器保存成。进入到gdb调试里边。展示一下设置的断点。删除的是第2个断点。原创 2023-03-29 23:24:39 · 2551 阅读 · 0 评论 -
gdb设置断点实战
此文章为3月Day 28学习笔记,内容来源于极客时间。上边的代码使用编辑器保存成。上边的代码用编辑器保存成。原创 2023-03-28 19:49:58 · 524 阅读 · 0 评论 -
gdb传递main方法的入参并使用条件设置断点
函数的参数传到程序中,注意“–args”后边已经要跟着有main函数的可执行文件。此文章为3月Day 27学习笔记,内容来源于极客时间。将“I love the world”字符当成。或者其他编辑器,保存成。进行输出调试信息编译。原创 2023-03-27 23:40:55 · 1094 阅读 · 0 评论 -
gdb断点暂停地方
一般而言,源代码中的行号与用户书写程序中的行号是一致的,但是有时候由于一些编译选项会导致行号不一致的情况,务必请看GDB中的行号。多了一行代码“printf(“There is more than one argument\n”);发现断点停留在第15行,程序恰好停在断点所在行前。默认是只有可执行文件作为参数传到程序中了。默认从输出第1行至第10行代码。看一下第10行到第19行代码,是开始运行,遇到断点会停下来。进行带有调试信息的编译。可以传参数进程序,比如。在第15行设置断点。可以查看设置的断点。原创 2023-03-26 23:41:35 · 545 阅读 · 0 评论 -
gdb设置断点的方式概述
进行带有调试信息的编译。关于如何使用list和run命令,可以参考。先执行可执行文件看看效果,若是输入。上边的代码的功能使用vim保存成。原创 2023-03-25 23:49:23 · 862 阅读 · 0 评论