《30天自制操作系统》读书笔记(2)hello, world

  • 让系统跑起来

  要写一个操作系统,我们首先要有一个储存系统的介质,原版书似乎是06年出版的,可惜那时候没有电脑,没想到作者用的还是软盘,现在的电脑谁有软驱?不得已我使用一张128M的SD卡来代替,而事实上你用的是U盘还是软盘对我们的操作系统没有影响,缺点是你的U盘刷入系统后容量只能是1440 MB,即当年流行的3.5英寸软盘的大小,当然不用担心,再格式化一次(用DiskGeniu),就可以恢复。

  我做事情的话,总是怕自己的努力的结果白费了,害怕辛辛苦苦看完这本书但是发现做出来的东西现在根本没法用,比如你花了大力气造了一辆火车,发现轮子的间距和现行标准不符,没轨道可以跑,被标准抛弃的感觉太恐怖,所以我决定试试,作者的系统能不能真正地跑起来。

我选择了源码中projects\30_day\harib27f中的haribote.img文件,用ImgWriter写入到我的储存卡,

  写入后的大小和预期相符,1.x MB;

  重新启动,开机时狂按Delete,修改启动项;

  F10保存后重启,心中有些忐忑不安;

  … …

  但是结果还是如我所愿,看,It works!

  这是就是我们要完成的东西了,偷窥胜利果实的快感不言而喻,系统甚至支持USB键盘,但不支持USB鼠标确实是不能用。我试着输入了几个命令:

  Bad command. 我也不知道什么是作者指定的command,已知的是,exit能用。

  • 用Virtual Box 代替物理机

  频繁地开关电脑来调试我们的系统是不理想的,我们需要Virtual Box来搭把手。

打开VB的控制台,新建虚拟机,操作系统的类型选Other,版本选择Other\Unknown,

一直点下一步直到虚拟硬盘,选择不添加虚拟硬盘,我们的虚拟硬盘文件就是img。

  选择虚拟电脑的设置——储存——储存树,添加一个软盘控制器,原来的IDE控制器可以删掉了,在软盘控制器里新增软盘到控制器,当然选择刚才的haribote.img,然后大功告成,启动系统。

  启动系统后一切都显得那么完美,鼠标能用,键盘也是,而且非常方便,输入的蹩脚英文或许有错,见笑了。

  PS: 这里需要注意的是本来有另一种方案,使用VB安装目录下的VBoxManage.exe 执行 VBoxManage convertdd  file.img file.vdi

但不知为何,没办法转换上述的haribote.img,只能转换下面要写的hello, world。

  • 动手写操作系统

  电脑启动的步骤是简要部分步骤是:加电——读取BIOS——自检——控制权移交操作系统(或者说引导),如此看来,我们的任务就是编写一段符合规范的代码,在第四步的时候代码会被执行。

  首先我们需要一个标准的FAT12的启动扇区(Boot sector)的代码,我很希望有FAT32 的,无奈这本书给的就是FAT12的,代码如下:

  但是这段完全由数据组成的代码只是符合了一个软盘启动扇区的标准,还没有任何可执行的代码:

 1  ; OS 0.01
 2 ; 标准FAT12软盘专用代码
 3
 4 DB 0xeb, 0x4e,0x90
 5 DB "HELLOIPL"     ; 启动扇区(boot sector)的名字
 6 DW 512            ; 每个扇区(sector)的大小:512B
 7 DB 1        ; 簇(cluster)的大小:一个扇区
 8 DW 1        ; FAT的起始位置
 9 DB 2        ; FAT的个数
10 DW 224        ; 根目录大小
11 DW 2880        ; 磁盘大小 2880扇区
12 DB 0xf0        ; 磁盘种类
13 DW 9        ; FAT长度
14 DW 18        ; 一个磁道(track)有18个扇区
15 DW 2        ; 磁头数
16 DD 0        ; 不使用分区
17 DD 2880        ; 重写磁盘大小
18 DB 0,0,,0x29    ; 固定
19 DD 0xffffffff    ; 意义不明
20 DB "HELLP_OS   "    ; 磁盘名称11字节
21 DB "FAT12   "    ; 磁盘的格式名称8字节
22 RESB 18        ; 空出18 Bit

  下面添加了可执行的代码,可以称作是IPL了。

 1 ; hello-os
 2 ; TAB=4
 3
 4 ORG        0x7c00    ;为什么这两句可以代替前面的 0xeb 0x4e?
 5 JMP        entry
 6 DB        0x90
 7 DB        "HELLOIPL"
 8 DW        512
 9 DB        1
10 DW        1
11 DB        2
12 DW        224
13 DW        2880
14 DB        0xf0
15 DW        9
16 DW        18
17 DW        2
18 DD        0
19 DD        2880
20 DB        0,0,0x29
21 DD        0xffffffff
22 DB        "HELLO-OS   "
23 DB        "FAT12   "
24 RESB    18
25
26 entry:
27 MOV        AX,0
28 MOV        SS,AX    ;这里改为 SS,0会出错
29 MOV        SP,0x7c00
30 MOV        DS,AX   
31 MOV        ES,AX
32 MOV        SI,msg   ;储存字符串的首地址
33 putloop:
34
35 MOV        AL,[SI]
36 ADD        SI,1
37 CMP        AL,0
38 JE         fin
39 MOV        AH,0x0e    ; int 0x10 的 0x0e号功能
40 MOV        BX,0x15 
41 INT        0x10
42 JMP        putloop
43 fin:
44 HLT
45 JMP        fin
46
47 msg:
48 DB        0x0a, 0x0a    ; ‘\n‘ = #13 = 0x0a
49 DB        "LastAvengers‘s OS"
50 DB        0x0a
51 DB        0       ; 结束标志
52
53 RESB    0x7dfe-$ ; 0x01fe+0x7c00 = 0x7dfe
54 DB        0x55, 0xaa
55 DB        0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00
56 RESB    4600
57 DB        0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00
58 RESB    1469432    

  使用作者提供的nask.exe,执行 nask.exe IPL.asm a.img 可以得到镜像文件,可以利用VB来启动了。

  • 简化操作流程:

  一开始作者为我们提供了install.bat,!cons_nt.bat,run.bat来安装和运行系统,后

来又介绍了make.exe,实在是神器,(之前还不解为什么在Linux下编译包需要make install,现在终于知道了),只需要构造一个不带扩展名的MakeFile文件,就可以集编译写入运行于一身,MakeFile 的基本格式如下:

宏定义  源文件之间的相互依赖关系
         任意可执行的Shell命令

作者在这里贸贸然地给出了

1 helloos.img : ipl.bin Makefile
2     ../z_tools/edimg.exe imgin:../z_tools/fdimg0at.tek 3         wbinimg src:ipl.bin len:512 from:0 to:0 imgout:helloos.img 

  先通过nask 生成bin文件再用edimg.exe 转为img文件,我不知道为什么要这么做,而且生成 .lst 文件的时候也失败了。

作者给出的makefile中地址都是斜杠,而系统用的是反斜杠,虽然效果一样,但是看着不爽,vim ":1,$/\//\\/g"可以将所有斜杠转化为反斜杠,注意这里的\有的是用来做转义的。

于是我没有照着他那样,我的MakeFile改写如下,同样正常工作:

 1 # nask.exe ipl.asm a.img ipl.lst ::fail NASK: LSTBUF is no enough
 2
 3 default :
 4     tolset\z_tools\make.exe install
 5     tolset\z_tools\make.exe    run
 6     del *.*~ >nul ::删除临时文件
 7     del *~ >nul
 8
 9
10 a.img : ipl.asm Makefile
11     tolset\z_tools\nask.exe ipl.asm a.img::直接编译成img,不知作者的用意是什么
12
13 install :
14     tolset\z_tools\make.exe -r a.img
15
16 run :
17     echo Running...
18     "D:\Program Files\Oracle\VirtualBox\VirtualBox.exe" --comment "OS1" --startvm "a5c4b0e6-e142-4720-98ee-056911204b29" ::虚拟机的快捷方式
19     echo Finished.

另外改写了!cons_nt.bat,增加了环境变量。

1 @echo off
2 color 0b
3 set PATH=%PATH%;tolset\z_tools4 cmd.exe 

之后打开!cons_nt.bat, 输入make,效果如图:

  • 知识点:

  FAT12启动区的标准:第511个字节开始填充55AA,软盘大小是2880*512/1024 = 1440 KB;

  启动区的加载地址是 0x7c00—0x7dff;

  各种寄存器,只有SI,DI,BX为数不多的几个寄存器才能放地址;

  MakeFile 的用法;

  Vim的替换命令;

  int 0x10中断重点是AH=0EH:http://blog.csdn.net/thimin/article/details/2313390

  唉,我真是话唠。

《30天自制操作系统》读书笔记(2)hello, world,布布扣,bubuko.com

时间: 2024-10-02 06:53:02

《30天自制操作系统》读书笔记(2)hello, world的相关文章

多定时器处理1(30天自制操作系统--读书笔记)

自认为写过很多MCU程序,但总是回头想想,我所了解的MCU编程思想大体有两种,其中具体的想法我得再找时间写下来. 总想总结出一个可扩展的,易移植的写法,但能力还没到这个层次.但<30天自制操作系统>这本书确实给我了一个思路,就像我已经写过的两篇读书笔记. 将两个独立的内容--FIFO和内存动态管理做到高度模块化,尤其是其中数据结构模型的设计更是我学习的好例子. 今天要学习的设计内容是多定时器处理.原书对这部分的处理讲的很详细,由浅入深,看得我由衷佩服作者,也可能是因为我水平低,稍稍看出点门道来

内存管理(30天自制操作系统--读书笔记)

今天继续读书笔记,“挑战内存管理”(30天自制操作系统). 为什么对这块内容敢兴趣呢,因为曾经遇到这么一个问题.在STM32程序中想使用队列,可不是上篇讲的FIFO,而是使用了较大的内存空间,又想做队列的顺序存取管理. 在这个队列里用到了malloc,动态申请内存,一开始是直接申请不到内存,后来在启动脚本里更改了设置堆的地址值,可以申请成功,但发现申请几次后,也申请不到内存. 果然MCU级别的程序,内存这块处理起来就没有windows程序那么随心所欲了.讲了这么多,开始正题吧. 1.相关数据结构

单字节的FIFO缓存(30天自制操作系统--读书笔记)

从今天起,写一些读书笔记.最近几个月都在看<30天自制操作系统这本书>,书虽说看的是电子书,但可以花钱买的正版书,既然花费了金钱,就总得有些收获. 任何人都不能总是固步自封,想要进步就得学习别人的知识,对于程序员而言,最简单的方法即是学习别人的代码. 今天的标题是“单字节的FIFO缓存”,其实就是做一个FIFO,看名字就知道了.也就4个函数和1个相关结构体,这样的小代码在嵌入式系统中很常用,也会很好用. 1.相关数据结构体 struct FIFO8 { unsigned char *buf;

多定时器处理2(30天自制操作系统 -- 读书笔记)

今天的内容依然来自<30天自制操作系统>这本书. 1.中断处理程序存在的问题,中断处理程序Timer_Interrupt如下: //定时器中断函数 void Timer_Interrupt(void) { int i=0; timerctl.count ++; for(i=0;i<MAX_TIMER;i++) //扫描所有的定时器 { if(timerctl.timer[i].flag == TIMER_FLAG_USING) { timerctl.count--; if(timerct

30天自制操作系统读书笔记(一)

刚开始作者叫我们用二进制编辑器,手敲01代码写了个IMG(磁盘映像文件) ,并提供了一些文件 : Run.bat, install.bat这些一个批处理文件,其实就是写好了cmd指令保存到文档里面,方便以后执行. 其中run.bat里面的指令是这样的 : copy helloos.img ..\z_tools\qemu\fdimage0.bin ..\z_tools\make.exe         -C ../z_tools/qemu (稍微解释一下:第一行:copy指令把,helloos.i

30天自制操作系统读书笔记(二)

我还以为马大哈的作者忘记解释之前那段好长的汇编代码了,留下这么多疑惑! 第二天作者就交代了:以后再讲,第二天我们先来谈谈程序核心部分的内容吧! 好吧,刚准备欢喜的等着作者解释,没想到他就扔了一大串代码(什么鬼?) ; hello-os ; TAB=4 ORG 0x7c00 ; 指明程序的装载地址,这个指令是和nask编译器说的(伪指令)告诉nask,开始执行的时候,把代码放到0x7c00的地方. ;为什么是0x7c00呢,因为规定了0x7c00-0x7dff是启动区的装载地址. ; 以下用于标准

30天自制操作系统读书笔记(五)

为了让程序灵活点,作者觉得把什么320X200这些数据直接写入程序,不如让程序自己获取. 所以就引入了结构体,指针.用指针直接在内存中获取这些数据 (如程序里的这句: Binfo_scrnx = (short *) 0xff4; ). 对于结构体和指针我就不细写了,有C语言基础的人都知道. 因为已经进入了32位模式,所以不能再用bios写好的中断程序给我们输出字符了,要手动了! 用像素点描出图形. 字符可以使用8X16的长方形像素点来表示,转变为16进制就是这样: static char fon

多定时器处理3(30天自制操作系统 -- 读书笔记)

继续定时器中断处理的改进. 1.定时器中断程序Timer_Interrupt是这样的. //定时器中断函数 void Timer_Interrupt(void) { int i=0; timerctl.count ++; for(i=0;i<MAX_TIMER;i++) //扫描所有的定时器 { if(timerctl.timer[i].flag == TIMER_FLAG_USING) { timerctl.count--; if(timerctl.count == 0) //减得时间到了 {

30天自制操作系统读书笔记(四)

想要在画面里画点什么东西,就需要往VRAM的内存区里写入点什么东西. 但是如何写入呢? 作者先用了汇编: _write_mem8:         ; void write_mem8(int addr, int data); MOV                  ECX,[ESP+4]               ; [ESP + 4]中存放的是地址,将其读入ECX MOV                  AL,[ESP+8]                 ; [ESP + 8]中存放的

《30天自制操作系统》笔记(12)——多任务入门

<30天自制操作系统>笔记(12)——多任务入门 进度回顾 上一篇介绍了设置显示器高分辨率的方法.本篇讲一下操作系统实现多任务的方法. 什么是多任务 对程序员来说,也许这是废话,不过还是说清楚比较好. 多任务就是让电脑同时运行多个程序(如一边写代码一边听音乐一边下载电影). 电脑的CPU只有固定有限的那么一个或几个,不可能真的同时运行多个程序.所以就用近似的方式,让多个程序轮换着运行.当轮换速度够快(0.01秒),给人的感觉就是"同时"运行了. 多任务之不实用版 我们首先从