自制操作系统-使用汇编显示 hello world
Posted sea-stream
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自制操作系统-使用汇编显示 hello world相关的知识,希望对你有一定的参考价值。
Windows (开机)读软盘第一个扇区的读法的具体表格
Hello World汇编版
就是将16进制编写的代码使用汇编语言编写出来
; cherry-os ORG 0x7c00 ;指定程序装载的位置 ;下面用于描述FAT12格式的软盘 JMP entry DB 0x90 DB "CHRRYIPL" ;启动区的名称可以是任意的字符串,但长度必须是8字节 DW 512; 每一个扇区的大小,必须是512字节 DB 1 ;簇的大小(必须为1个扇区) DW 1 ;FAT的起始位置(一般从第一个扇区开始) DB 2 ;FAT的个数 必须是2 DW 224;根目录的大小 一般是224项 DW 2880; 该磁盘的大小 必须是2880扇区 DB 0xf0;磁盘的种类 必须是0xf0 DW 9;FAT的长度 必须是9扇区 DW 18;1个磁道(track) 有几个扇区 必须是18 DW 2; 磁头个数 必须是2 DD 0; 不使用分区,必须是0 DD 2880; 重写一次磁盘大小 DB 0,0,0x29 ;扩展引导标记 固定0x29 DD 0xffffffff ;卷列序号 DB "CHERRY-OS " ;磁盘的名称(11个字节) DB "FAT12 " ;磁盘的格式名称(8字节) TIMES 18 DB 0; 先空出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 ;调用显卡Bios JMP putloop fin: HLT ;CPU停止,等待指令 JMP fin ;无限循环 msg: DB 0x0a , 0x0a ;换行两次 DB "hello, cherryOS" DB 0x0a DB 0 TIMES 0x1fe-($-$$) DB 0 ;填写0x00,直到0x001fe DB 0x55, 0xaa
将这个文件保存为cherryOS.asm,使用nasm生成cherryOS.img
nasm cherryOS.asm -o cherryOS.img
使用QEMU运行我们的系统
qemu-system-i386 cherryOS.img
效果图:
代码说明
书中使用的是NASK,我们使用的是NASM,部分语法不同,这里总结一下。
1
2
3
4
5
|
NASK代码 NASM代码
JMP entry -> JMP SHORT entry
RESB <填充字节数> -> TIMES <填充字节数> DB <填充数据>
RESB 0x7dfe-$ -> TIMES 0x1fe-($-$$) DB 0
|
下面对一个语句做专门说明
1
|
TIMES 0x1fe-($-$$) DB 0
|
这一句其中出现了$与$$这样的符号。
$ 是当前位置
$$ 是段开始位置
$ - $$ 是当前位置在段内的偏移
比如我们前面输入了130个字节,那么$ - $$就是130,使用0x1fe-($ - $$)就可以计算出到达0x1fe还需要多少个字节。
这样就保证了我们循环填充后所停在的位置是0x1fe
上面的代码中出现了FAT12格式,IPL这样的词语。这里简要说明。
FAT12: Windows MS-DOS所采用的软盘格式。后面我们将使用FAT32作为我们系统的格式。
启动区: 软盘的第一个扇区成为启动区。
扇区: 计算机读写软盘的过程中不是一个字节一个字节的读写,而是以512字节为一个单位进行读写的。因此,软盘的512个字节就是一个扇区。扇区就是最小的读写单元。
IPL:initial program loader的缩写。启动程序加载器,启动区只有区区512字节,实在是太小了。所以我们需要一个专门的程序IPL去启动操作系统
bootsrap:鞋带。操作系统的启动就是操作系统的一个自救过程,我们一般将操作系统的启动机制叫做bootstrap。
几个语句:
ORG:这个指令将告诉编译器,在代码开始执行的时候,这些代码将被装载到哪个地址中,比如我们在这里指定的地址是0x7c00。(为什么是0x7c00,IBM的大佬们当年规定的就是这个数字,我也没办法)
JMP:JMP,跳转,转到对应的语句。
MOV:这个不多说了,相当于赋值语句。MOV AX,0 就是将0赋值给AX
HLT:让CPU停止动作的指令,并不是完全的停止,只是让CPU进入等待状态。
INT:BIOS中断指令,这里我们用到INT0x10调用显卡,更多的有关BIOS的中断可以自行百度。
四个代码块:
entry:程序的开始,主要用来初始化寄存器和将msg的地址放入SI
putloop:用于显示一个字符,整个流程就是这个代码段所表示的过程,AH默认0x0e,AL表示字符,BH默认为0,BL表示颜色。具体参考INT0x10中断内容。
fin:让CPU进行等待。这个代码段要在代码中看,我们是这么写的CMP AL,0 JE fin。JE表示 jump if equal。所以这句话的意思是,如果AL==0 那么跳转到fin。也就是说我们msg中的信息显示完成后,就让CPU进入无限等待状态。
msg:用于显示我们的内容
几个寄存器:
虽然这都是基础了,但是还是写一下,省的大家百度了
AX 累加寄存器 BX 基址寄存器 CX计数寄存器 DX数据寄存器
SP 栈指针寄存器 BP 基址指针寄存器 SI 源变址寄存器 DI 目的变址寄存器
ES 附加段寄存器 CS 代码段寄存器 SS 堆栈段寄存器 DS 数据段寄存器
L与H:H表示高位,L表示地位,AL表示AX寄存器低位,AH表示AX寄存器的高位
整体流程:
- 首先进入entry,entry中完成了对寄存器的初始化,并且将msg的地址放到SI中,此时可以将SI理解成一个在msg数据中滑动的指针。
- msg内部是我们需要显示的字符串
- 进入putloop,这个循环用于将msg的字符一个一个打印出来。如果AH = 0时,进入fin。
- 进入fin,程序变为无限等待状态。
参考:
http://blackblog.tech/2018/07/18/CreateOSDay2/
以上是关于自制操作系统-使用汇编显示 hello world的主要内容,如果未能解决你的问题,请参考以下文章