最简单的操作系统:Hello World
说是操作系统,更准确的说,直接利用CPU输出“Hello World”到显示器。
在我的理解是,这个所谓的最简单的操作系统,连实模式都不算。
上代码
好了,开始上代码,看看直接的效果。我的习惯是先看效果,再去分析和理解代码。
显示器上显示“Hello World”有两种办法,
一个是调用BIOS中断int 10h。
一个是不走BIOS,直接调用Text的显示端口0xb800(有助于理解VGA的显存端口0xa0000~0xaffff)。
关于端口参考:https://blog.csdn.net/jinold/article/details/86991055
1. 调用int 10h中断实现
org 07c00h ;告诉计算机将代码加载到内存的07c00h
mov ax, cs
mov ds, ax ;初始化数据段ds
mov es, ax ;初始化附加段寄存器
call DispStr ;调用DispStr来显示字符串
jmp $ ;无限循环
DispStr:
mov ax, BootMessage ;将字符串地址传给寄存器ax
mov bp, ax ;通过ES:BP来指向显示的字符串
mov cx, 32 ;表示字符串的长度
mov ax, 01301h ;10h的13号中断,此时通过AH=13传入,AL=1,表示目标字符串仅仅包含字符,属性在BL中包含,移动光标
mov bx, 000ch ;BH表示视频区页数,BL表示颜色
mov dl, 0 ;DL表示在第几列显示(0为第一列)
int 10h ;10H中断
ret
BootMessage: db "Hello,OS World!"
times 510-($-$$) db 0 ;用times来创建字节0
dw 0xaa55 ;扇区结尾,写入引导程序标志位
2. 直接用0xb800端口
mov ax, 0xb800 ;表示的是显存起始位置(后面还会提到)
mov ds, ax
mov byte [0x00], 'H' ;打印 Hello World!
mov byte [0x01],0x07
mov byte [0x02], 'e'
mov byte [0x01],0x07
mov byte [0x04], 'l'
mov byte [0x01],0x07
mov byte [0x06], 'l'
mov byte [0x01],0x07
mov byte [0x08], 'o'
mov byte [0x01],0x07
mov byte [0x0C], 'w'
mov byte [0x01],0x07
mov byte [0x0E], 'o'
mov byte [0x01],0x07
mov byte [0x10], 'r'
mov byte [0x01],0x07
mov byte [0x12], 'l'
mov byte [0x01],0x07
mov byte [0x14], 'd'
mov byte [0x01],0x07
mov byte [0x16], '!'
mov byte [0x01],0x07
jmp $ ;让 CPU 挂这里
times 393 db 0
db 0x55, 0xaa ;虚拟机需要检测 MBR 标记
3. 引导扇区
代码的最后两句可以不写的(VM下试过没有问题,Hyper-v不行,VBox没试过)。
意思是这是引导程序。
times 510-($-$$) db 0 ;用times来创建字节0
db 0x55, 0xaa ;引导扇区结尾,写入引导程序标志位
编译上面的代码
nasm helloworld.asm -o helloworld.img
helloworld.img其实就是bin文件。为了方便虚拟机能识别,取了img的名称。
用十六进制编程器打开看看helloworld.img。
如下图,去掉了最后两句的效果。
把这个img文件复制到软盘镜像的引导区,和加上被删除的两行代码后编译、运行,效果一样的。
软盘镜像的工具就多了,WinImage、UltraISO等等