网上有不少简单的加载器制作的文章,我也是初学,之前看过《Oranges‘s 一个操作系统的实现》,看到保护模式哪一点觉得非常头痛,有很多不清楚的地方,现在在看《30天自制操作系统》,虽然读起来简单多了,不过我使用的是Linux系统,做起来还是有些麻烦,此系列文章可以当作简单的学习笔记,不过会加上我个人的理解,将我当初迷茫的地方写出来,以及如何在Linux系统上搭建起操作系统的实验环境。最近一年准备主攻编译器和操作系统,希望能和大家一起学习,进步。
准备环境:
Hello world
org 0x7c00 ; 告知nasm,代码会加载在0x7c00处,详细解释在后面
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 ; 换行'\n'的ASCII码为10=0x0a
db "Hello,world"
db 0x0a
db 0
times 510-($-$$) db 0 ;重复到510字节处
db 0x55,0xaa ;启动扇区标识
run : bochs a.img
bochs -q #启动
bin :
nasm -f bin hello.asm -o hello.bin #编译生成bin格式文件
a.img : bin img
dd if=./hello.bin of=./a.img bs=512 count=1 conv=notrunc #将生成的文件写入软盘镜像
img :
bximage -q -fd -size=1.44 a.img > /dev/null #创建软盘镜像
bochs:
cp ~/bochsrc ./ #复制bochsrc到当前目录,这点实验的时候看情况更改
clean:
-rm -f hello.bin bochsrc a.img
下面是复制过来的bochsrc###############################################################
# Configuration file for Bochs
###############################################################
# how much memory the emulated machine will have
megs: 32
cpu: ips=10000000
# filename of ROM images
romimage: file=/usr/local/share/bochs/BIOS-bochs-latest
vgaromimage: file=/usr/local/share/bochs/VGABIOS-lgpl-latest
# what disk images will be used
floppya: 1_44=a.img, status=inserted
# choose the boot disk.
boot: floppy
# where do we send log messages?
# log: bochsout.txt
# disable the mouse
mouse: enabled=1
# enable key mapping, using US layout as default.
keyboard_mapping: enabled=1, map=/usr/local/share/bochs/keymaps/x11-pc-us.map
现在,make以下,bochs运行,输入c(表示继续,debug版本的bochs),可以看到模拟器上显示了Hello,world。
00000000 8CC8 mov ax,cs
00000002 8ED0 mov ss,ax
00000004 8ED8 mov ds,ax
00000006 8EC0 mov es,ax
00000008 BE237C mov si,0x7c23
0000000B 8A04 mov al,[si]
0000000D 81C60100 add si,0x1
00000011 3C00 cmp al,0x0
可以看到,mov si,0x7c23 这一条指令,在代码里,写的是 mov si,msg.如果我们去掉前面的org 0x7c00的话,这里的指令就成了mov si,0x23.显然,如果其他寄存器都为0的话,此时下面显示字符串的指令肯定会出错,因为地址有问题。讲到这就可以知道,org 0x7c00并不是必须的,我们完全可以使用其他的方式到达同样的目的,比如像下面这样修改:jmp 0x7c0:entry
entry:
mov ax,cs
mov ss,ax
mov ds,ax
mov es,ax
mov si,msg
这样的话,执行跳转时CS会被设置为0x7c0,其他寄存器也被下面的指令初始化为0x7c0,就不会产生问题了。