顾名思义,本书将制作操作系统的整个过程分成了30天来依次讲解。但其实每一天的内容多少与难度各不相同,也并不是每天就可以学习完书中一天的内容。前面的内容要少一些,也比较基础,因此先把第一天和第二天的内容合并起来整理。
1.二进制与CPU
作者没有从概念开始讲起,而是开篇就指导读者用二进制编辑器编写一个二进制文件,运行之后可以直接打印出一些信息。
用高级语言编程久了,偶尔会忘了其实我们编写的一切代码都要转换成0和1组成的二进制序列提供给CPU去处理。同样的一串序列,根据不同的解释方法,可以被解释成图片或文字,也可以被解释成程序。正如作者所说的,也许把一张照片的二进制编码解释成程序,可以获得一个完美的操作系统呢。理论上来说不是没有可能,但这种可能性实在是太低太低了。
2.汇编语言初步
上面由二进制编辑器来直接制作出二进制文件只是为了讲解二进制的重要性,接下来作者准备把上面的二进制内容通过汇编语言来实现。
; hello-os
; TAB=4
;
DB 0xeb, 0x4e, 0x90
DB "HELLOIPL" ;
DW 512 ;
DB 1 ;
DW 1 ;
DB 2 ;
DW 224 ;
DW 2880 ;
DB 0xf0 ;
DW 9 ;
DW 18 ;
DW 2 ;
DD 0 ;
DD 2880 ;
DB 0,0,0x29 ;
DD 0xffffffff ;
DB "HELLO-OS " ;
DB "FAT12 " ;
RESB 18 ;
;
DB 0xb8, 0x00, 0x00, 0x8e, 0xd0, 0xbc, 0x00, 0x7c
DB 0x8e, 0xd8, 0x8e, 0xc0, 0xbe, 0x74, 0x7c, 0x8a
DB 0x04, 0x83, 0xc6, 0x01, 0x3c, 0x00, 0x74, 0x09
DB 0xb4, 0x0e, 0xbb, 0x0f, 0x00, 0xcd, 0x10, 0xeb
DB 0xee, 0xf4, 0xeb, 0xfd
;
DB 0x0a, 0x0a ;
DB "hello, world"
DB 0x0a ;
DB 0
RESB 0x1fe-$ ;
DB 0x55, 0xaa
;
DB 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00
RESB 4600
DB 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00
RESB 1469432
汇编语言中,分号";“后的内容表示注释,作用相当于C语言中的”//"。
其实这里主要还是用DB指令来写入了大部分的数据,相当与模拟二进制的结果。DB指令是define byte的缩写,在汇编语言中可以用来写入一个字节的数据。相应的还有DW,DD,分别是define word和define double word的缩写。这里word指的是两个字节,而double word就是四个字节了。
除了写入的部分数据,还有大量空间没有写入数据,这里就用到了RESB指令,是reserve byte的缩写。使用RESB 10就表示空出10字节的空间,并且会自动填充为0x00。
3.几个主要术语的解释
看到这里其实有些懵,之前的二进制文件运行之后确实能够输出一些内容,上面这一段程序其实也只是执行一些初始化的动作以及显示一行字,但这就是操作系统吗?这里涉及到了一些术语和概念。
首先是启动区。虽然作者在书中使用的是软盘,但读取磁盘的时候也是分扇区进行读取的,一个扇区的大小是512字节,这在后面也会有更详细的讲解。而计算机读入的第一个扇区就被称为启动区。这个扇区的结尾两个字节一定是0x55 0xAA,否则计算机会无法识别启动程序,无法启动。
IPL又是什么呢?它是initial program loader的缩写,即启动程序加载器。启动区虽然只有512字节,但其中的内容却是加载操作系统本身的程序,因此通常将启动区称为IPL。
操作系统的启动称为boot,这个词本是长靴,但后来具有了“自力更生完成任务”的意思。操作系统的程序的程序与启动区的程序都装载在硬盘上,上电后需要通过启动区的程序去读取操作系统本身的程序,实现操作系统的启动,大概这就是boot这个词想表达的意思吧。
因此前面的这段程序,其实是在为制作操作系统的第一关——IPL做准备。
第二天的内容中作者继续介绍汇编语言。作者介绍了一款文本编辑器,但由于是日语版本,用起来并不方便。还是使用中文版的Notepad++软件更为方便,同样是一款免费软件,下载安装都很简单。
第一天的程序虽然也是用汇编语言编写,但其实大部分使用DB直接写入数据,也就是将汇编语言代码编译后生成的二进制内容直接写入,这里则是解析生成这些二进制内容的汇编语言代码。
; hello-os
; TAB=4
ORG 0x7c00 ;
;
JMP entry
DB 0x90
DB "HELLOIPL" ;
DW 512 ;
DB 1 ;
DW 1 ;
DB 2 ;
DW 224 ;
DW 2880 ;
DB 0xf0 ;
DW 9 ;
DW 18 ;
DW 2 ;
DD 0 ;
DD 2880 ;
DB 0,0,0x29 ;
DD 0xffffffff ;
DB "HELLO-OS " ;
DB "FAT12 " ;
RESB 18 ;
entry:
MOV AX,0 ;
MOV SS,AX
MOV SP,0x7c00
MOV DS,AX
MOV ES,AX
MOV SI,msg
putloop:
MOV AL,[SI]
ADD SI,1 ;
CMP AL,0
JE fin
MOV AH,0x0e ;
MOV BX,15 ;
INT 0x10 ;
JMP putloop
fin:
HLT ;
JMP fin ;
msg:
DB 0x0a, 0x0a ; 换行两次
DB "hello, world"
DB 0x0a ; 换行
DB 0
RESB 0x7dfe-$ ; 填充0x00
DB 0x55, 0xaa
1.主要寄存器介绍
为了更好地理解代码,还是要先总结一下寄存器的内容。其实寄存器这个概念对于有些计算机和嵌入式基础的同学来说并不陌生,经常会用到,但对于如何解释它的定义,细想之下似乎没法给出一个很准确的定义。用作者的话说,CPU的寄存器是CPU内部的一种存储电路,机器语言中相当于变量的功能。
CPU中主要的寄存器有以下8个:
AX:累加寄存器
CX:计数寄存器
DX:数据寄存器
BX:基址寄存器
SP:栈指针寄存器
BP:基址指针寄存器
SI:源变址寄存器
DI:目的变址寄存器
这些寄存器都是16位的。而对于AX,CX,DX,BX这4个寄存器,又可以分别使用其高8位与低8位,如AH指AX寄存器的高8位,而AL则是AX寄存器的低8位。当前并没有全部用到,这里初步了解,后面的内容中这些寄存器还是由重要作用的。
如果只使用CPU的寄存器,其实能够存储的数据量是非常小的,只有区区16个字节。因此程序和变量需要存放在内存中,在运行过程中再由CPU从内存中读取。
2.继续学习汇编代码
这样就可以继续解释这段汇编代码了。
ORG指令是用来指定装载内存地址的。程序运行时会将程序加载到内存的这个位置,并从这个位置开始执行。
JMP指令则是跳转指令,是指跳转到某一内存地址执行,而entry则是后面定义的一个标号,其实代表这一个内存地址。执行JMP entry就是跳转到entry标号处的内存地址开始执行。
entry到putloop之间的代码主要进行了寄存器初始化。其中MOV指令算是汇编语言里面最基础和最常用的指令了,类似于C语言中的赋值指令。比如程序中的MOV AX, 0 相当于将寄存器AX赋值为0。而SS,DS,ES等几个寄存器无法直接进行赋值,需要通过AX寄存器进行中转。
MOV SI, msg这条指令则是指将msg标签的内存地址赋值给SI寄存器。可以看到msg位置定义的是一些文字内容,这就是后续 将要显示出来的内容。
接下来的putloop部分则是一个循环,用于显示msg定义的文字内容。
"[]“符号表示的则是”[]"中寄存器所存储的内存地址中的内容。因此MOV AL, [SI]就表示将SI寄存器中的内存地址内容赋值给AL。CMP是一个比较指令,这里是与JE指令结合使用。CMP AL,0即比较AL寄存器与0的值,紧接着JE fin则表示如果AL寄存器的值与0相等,则跳转到标号为fin的位置执行。ADD指令顾名思义是累加的意思,ADD SI, 1 即表示将SI寄存器的值加1。putloop的前四行即是从msg标号开始不断向前移动,并将内容存放在AL寄存器中,直到获取到的内容为0。
而后四行则是调用BIOS中断来依次显示字符。
BIOS程序在出厂时已经存储于主板的ROM中了,其中包括很多操作系统开发所需要的功能,可以直接进行调用。INT指令后面的数字即是调用BIOS功能的号码,而根据BIOS手册,调用这个功能需要的参数:
AH=0x0e
AL=字符编码
BH=0
BL=颜色编码
这样putloop这一段程序就将msg所定义的文字内容完全显示出来了。
最后fin标签的代码其实是一个死循环。HLT是让CPU进入待机状态的指令,如有其他操作还可以进行唤醒。于是显示完上面的文字内容之后,CPU就进入了待机状态。
3.Makefile入门
为了生成可执行文件,Makefile还是必不可少的。简单来说,Makefile其实描述的就是编译的目标,所需的依赖与如何生成目标的方法。基本语法就是:
目标:依赖
生成目标执行的指令
比如:
ipl.bin : ipl.nas Makefile
../z_tools/nask.exe ipl.nas ipl.bin ipl.lst
这里描述的就是为了生成ipl.bin,需要ipl.nas文件与Makefile文件,而生成的指令为…/z_tools/nask.exe ipl.nas ipl.bin ipl.lst
对于暂时找不到的文件,make会继续在Makefile中寻找,直到找到所有的依赖,并最终生成目标文件。
(Makefile这部分在第二天的内容里面作者讲的比较简略,后续再查找其他资料进行详细说明。)
这部分汇编代码,作者的意图是制作IPL,用于加载操作系统的程序。但是当前只实现了显示一行字的功能,不是真正的IPL。实现IPL功能的部分,作者在第三天的内容中继续进行了介绍,将在下一篇笔记中继续记录。
标签:0x00,读书笔记,Day2,30,DB,MOV,指令,寄存器,DW From: https://blog.csdn.net/Ocean1994/article/details/140999082