0,0
0,0
计算机启动过程:按指令执行顺序划分为3个过程
启动扇区:
启动扇区位于硬盘的0面0道1扇区,只有512个字节,判断一个扇区是否为启动扇区,cpu只是简单的做了两次判断:
这两个条件满足,就认为是启动扇区。
所以做一个简单的启动扇区只需要按下面这样做:
就3条汇编指令,“;”后面的都是注释。
;最简单的启动扇区
;启动扇区的判断条件:第一个字节不为0x00字节,最后两个字节为0x55,0xaa
;cpu执行全为0x00字节时会跳过,然后就会停住
;一个扇区为512个字节
db 0x01;保证第一个字节不为0x00字节
times 510-($-$$) db 0 ;剩余的509个字节用0字节填充。
;times n表示执行n次指令,$表示当前指令的内存偏移地址,$$表示扇区的开始地址,$-$$表示从扇区到当前指令的字节数
db 0x55,0xaa ;启动扇区flag标志
然后测试结果。
我使用VM Box虚拟机进行测试,新建一个虚拟机,启动设备设置为软盘,
用nasm工具把写好的汇编代码easyBootSector.asm汇编成二进制文件easyBootSector.img
.img文件是软盘文件,类似于镜像文件.iso,用哪种都类似,主要是要简单。
用winhex察看一下二进制机器码:
机器码里就只有3个字节不是0字节,ok,配置好镜像文件,启动。
结果如下:
只显示了一个下划线就halt待机了,什么显示也没有,因为没有做任何操作啊。
没有报操作系统未找到的错证明已经成功了。下面我们让它变得更漂亮。
-_-
BIOS作为ROM存储器里面保存了很多INT 中断函数,可以完成硬件的检测与初始化工作。自然,向显卡中输入数据控制显示器的输出也是可以的。
int 0x10中断函数就可以输出一个字符串,但是你要先给他传参数,他会自动从AX,BX等寄存器中取参数。
所以类似于下面可以输出一个字节的字符:
参考资料见:int 10h中断例程
mov AH,0x0e ;AX累加寄存器的高8位,选择功能,0x0e为打印字符
mov AL,0x68 ;AX的低8位,字符码,0x68=h,其实就是ascii码也是机器码
mov BH,0 ;可以不设置
mov BL,00001011b ;8位颜色码,图形模式下可以设置颜色
int 0x10 ;调用函数,根据AH选择特定的功能,可以是打印也可以是设置光标位置
使用int 0x10中断函数打印一个字符:
-,-
;bootSector
;利用bios的int 0x10中断函数操作显卡显示字符串
ORG 0x7c00;指明程序在内存中的装载位置,这样才能使用SI
jmp entry;跳转到指令执行位置
msg:
db "hello,world!" ;要显示的字符串,10
db 0x0D,0x0A;回车换行一次,int 0x10可以解释控制指令
;输出字符串int 0x10(AH,AL,BH,BL);
entry:
mov SI,msg
;循环输出hello,world,一个字节一个字节的输出
mov cx,14;循环次数
s:
mov AH,0x0e
mov AL,[SI];字符码
mov Bh,0
mov BL,00001101b;颜色码,没用
int 0x10;输出一个字符
inc SI
loop s
HLT ;halt,待机
times 510-($-$$) db 0;剩余的字节用0字节填充。
;times n表示执行n次指令,$表示当前指令的内存偏移地址,$$表示扇区的开始地址,$-$$表示从扇区到当前指令的字节数
db 0x55,0xaa
参考书籍:30天自制操作系统
现在这个启动扇区只能被识别,没有其它功能,要想真正的实现功能还得实现IPL加载器,也就是jmp一下了。