admin 管理员组

文章数量: 887021

目录

  • 写在前面
  • 参考资料
  • 开始动手
    • 写一个最小的操作系统
    • 调试.COM
    • 环境配置(Linux)
      • 用VisualBox虚拟器运行Ubuntu系统
      • 安装Linux系统
      • Dell笔记本的BIOS配置
  • 保护模式
    • 理解实模式和保护模式
    • 增加一个用LDT描述的任务
    • 特权集

写在前面

笔者目前大二,学过C++,汇编,操作系统,正在学习编译原理和计算机网络,打算做一个小的操作系统来巩固知识,加深对计算机的理解。

参考资料

目前正在学习《自己动手写操作系统》,资源参考一下博客:
自己动手写操作系统(高清图书+源代码)分享

开始动手

写一个最小的操作系统

一开始就遇到困难了,书中说10分钟完成一个操作系统,我花了一个小时了环境都没弄好,好在学计算机的不怕折腾,先附张结果图:

下面详述步骤:
参考文档:

  • 《自己动手写操作系统》—— 工作环境搭建
  • 30天自制操作系统第一天–VirtualBox实现软盘启动

步骤:
1.首先去官网下载安装NASM,配置环境变量,网址
2.下载虚拟机VirtualBox,网址(需要科学上网)
3.编写源代码,利用NASM编译成.bin文件,使用FloppyWriter.exe将文件写到TINIX.IMG文件里,经调试直接将后缀bin改成IMG好像也可以
4.新建一个虚拟机,网址,已经讲得很详细了,需要注意的是添加软盘选择IMG文件,我运行的时候试了几次才出现红色的“Hello,OS World!”,也不知道是什么原因。

这真的是太棒了,虽然你知道它有多么简陋,但是,毕竟你已经制作了一个可以引导的软盘了,而且所有工作都是你亲手独立完成的!

调试.COM

经历了一个寒假,汇编都忘得一干二净了,不得不从以前的教学文档里找回一些零星的记忆。
还好DOSBox还在,如果没有DOSBox,建议去官网下载一个,我找到了我安装Masm的地方,在旁边又把Nasm再安装了一遍(这样就不用在DOSBox\DOSBox-0.74\DOSBox 0.74 Options.bat里再配置一遍虚拟C盘了)

将boot.asm中的第一句改成org 07c00h,输入nasm boot.asm -o boot,打开DOSBox,找到boot运行就能看到左上角的"Hello,OS World"了
(由于jmp $这条语句,目前应当是卡死了的)
也可以使用debug工具直接调试的

汇编课上学到的东西,终于派上用场啦!

环境配置(Linux)

用VisualBox虚拟器运行Ubuntu系统

按照书上所说,可以用虚拟器运行Linux系统,但是书上只给出了Visual PC版的安装方法,如果使用VisualBox的话就要用别的方法了
参考文档:Linux下载安装过程 官网
这两篇教程应该足够了,只是耗费的时间比较长,如果顺利的话,Tinix应该可以运行了

安装Linux系统

VisualBox虚拟器上的Linux系统虽然容易安装,但运行起来实在是太慢了,随便一个命令都要等上好几秒甚至几十秒,像打开filefox这种直接就卡死机了,特别耽误时间而且影响心态(不知道是不是我电脑的问题),总之,磨了一天多终于把Linux系统给装上了,反正迟早要装的。
参考链接:
1.新手安装 Ubuntu 操作系统步骤教程
2.Ubuntu18.04安装教程

Dell笔记本的BIOS配置


如果都能按教程的来不出错的话,安装过程将会容易得多,不知道是不是版本问题,我的BIOS和教程总有一些出入,每次教程看得一半就做不下去了,下面的博客整理了一些问题,希望大家安装顺利!
关于dell设置U盘启动与安装Ubuntu的几个问题

安装Ubuntu后需要一些配置,写给工程师的 Ubuntu 20.04 最佳配置指南

保护模式

理解实模式和保护模式

由于各种原因,保护模式这章我卡了特别久,现在来整理一下。
参考文档:
实模式与保护模式解惑之(一)——二者的起源与区别
实模式和保护模式区别及寻址方式
为了更方便的理解汇编代码,首先要清楚两种模式在寻址方式上的区别,了解开设A20线的意义(第一篇文章有提到),才能理解为什么进入保护模式前要先打开地址线A20。

(个人理解)保护模式其中“保护”的含义就是要保护系统程序,让用户程序不能随便动系统程序空间的代码,这个其实在我们操作系统课里学过,就是分段操作,不过实模式下虽然有segment的概念,由于采用 hysicaladdress=segment * 16 + offset 的模式,对保护系统程序并没有什么作用;而保护模式中通过段选择符指向段描述符,再由段描述符指向段段基址加上段内偏移地址得出线性地址(详见第二篇文章),其中段描述符的S位和TYPE字段又将相应段分为了数据段、代码段和系统段,不同段有不同的权限,从而真正体现了保护的作用。

增加一个用LDT描述的任务

不来点实战真的不知道自己在看的什么。。。
正好看到书上62面有一个“读者有兴趣可以完成小任务”,做着试试看吧。

为了不搞复杂了,就熟悉熟悉LDT的用法,我们新建一个描述符表MYLDT,考虑到汇编不好调试的问题,为了少磨点心态,我们就把显示的“L”替换成“S”,证明我们改过来了,开干!

  1. 增加一个32位的代码段CodeB
; CodeB (MYLDT, 32 位代码段)             自己加的LDT代码段,打印一个S
[SECTION .la]
ALIGN	32
[BITS	32]
LABEL_CODE_B:
	mov	ax, SelectorVideo
	mov	gs, ax			; 视频段选择子(目的)

	mov	edi, (80 * 12 + 0) * 2	; 屏幕第 10 行, 第 0 列。
	mov	ah, 0Ch			; 0000: 黑底    1100: 红字
	mov	al, 'S'
	mov	[gs:edi], ax

	; 准备经由16位代码段跳回实模式
	jmp	SelectorCode16:0
CodeBLen	equ	$ - LABEL_CODE_B
; END of [SECTION .la]
  1. 增加描述符表
;MYLDT                      ;自己加的MYLDT段,内容是一个LDT描述符表,其中只有一个代码段描述符
[SECTION .ldt]
ALIGN     32
LABEL_MYLDT:
;
LABEL_MYLDT_DESC_CODEB: Descriptor 0,CodeBLen-1,DA_C+DA_32;Code,32位

MYLDTLen equ $-LABEL_MYLDT
;MYLDT选择子
SelectorMYLDTCodeB equ LABEL_MYLDT_DESC_CODEB - LABEL_MYLDT+SA_TIL
; END of [SECTION .ldt]
  • 在GDT中加入MYLDT段描述符与段选择子
LABEL_DESC_MYLDT:		Descriptor	       0,        MYLDTLen - 1, DA_LDT	;MYLDT      自己加的,用来描述MYLDT
SelectorMYLDT                        equ          LABEL_DESC_MYLDT	- LABEL_GDT    ;自己加的,用来作MYLDT段选择子
  • 初始化
; 初始化 MYLDT 在 GDT 中的描述符                                                                                      ;自己加的,初始化MYLDT
	xor	eax, eax
	mov	ax, ds
	shl	eax, 4
	add	eax, LABEL_MYLDT
	mov	word [LABEL_DESC_MYLDT + 2], ax
	shr	eax, 16
	mov	byte [LABEL_DESC_MYLDT + 4], al
	mov	byte [LABEL_DESC_MYLDT + 7], ah

	; 初始化 MYLDT 中的描述符
	xor	eax, eax
	mov	ax, ds
	shl	eax, 4
	add	eax, LABEL_CODE_B
	mov	word [LABEL_MYLDT_DESC_CODEB + 2], ax
	shr	eax, 16
	mov	byte [LABEL_MYLDT_DESC_CODEB + 4], al
	mov	byte [LABEL_MYLDT_DESC_CODEB + 7], ah
  • 加载MYLDT
; Load MYLDT                                                                                         这里改为MYLDT
	mov	ax, SelectorMYLDT
	lldt	ax

	;jmp	SelectorLDTCodeA:0	; 跳入局部任务
	jmp	SelectorMYLDTCodeB:0	; 跳入局部任务
  • 编译
    首先还是提醒一下最好别打错字了,段选择子和段描述符标签最好复制粘贴,不细心的话编译的时候可能就要像我这样一个个改了

    告诉大家一个技巧,记事本行头虽然没有行号标名,右下角的状态栏还是有的,根据错误行数的提示可以快速定位到相应行数,加快debug速度。
  • 运行

    可以看到红色的L变为S了,nice!

特权集

个人认为特权集是保护模式最本质待部分了,书上也讲得十分复杂,我们来理顺一下。

  • CPL(Current Privilege Level) 当前执行的程序或任务的特权级 存储在CS和SS的第0位和第1位上
  • DPL(Descriptor Privilege level) 表示段或者门的特权级 存储在段描述符或者门描述符的DPL中
  • RPL(Requested Privilege Level) 避免低特权级应用程序访问高特权级段内的数据 通过段选择子的第0位和第1位表现

再对不同段整理一下

  • 访问数据段或者调用门或者TSS:CPL,RPL<=被访问DPL
  • 访问非一致代码段(不使用调用门):RPL<CPL=被访问DPL
  • 访问非一致代码段(使用调用门):CPL>被访问DPL,RPL不检查
  • 访问一致代码段:CPL>被访问DPL,RPL不检查

本文标签: 手把手教你 操作系统