一个操作系统的实现笔记:引导扇区实现

实验环境:
· ubuntu18.04
· qemu
· nasm

1.安装需软件

  • qemu安装,请参考

  • nasm安装 sudo apt-get install nasm

2.编写引导扇区代码a.asm

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
	org	07c00h			; 告诉编译器程序加载到7c00处
mov ax, cs
mov ds, ax
mov es, ax
call DispStr ; 调用显示字符串例程
jmp $ ; 无限循环
DispStr:
mov ax, BootMessage ;将字符串首地址传递给寄存器ax
mov bp, ax ; ES:BP = 串地址,指向BootMessage
mov cx, 16 ; CX = 串长度
mov ax, 01301h ; AH = 13, AL = 01h
mov bx, 000ch ; 页号为0(BH = 0) 黑底红字(BL = 0Ch,高亮)
mov dl, 0
int 10h ; 10h 号中断
ret
BootMessage: db "Hello, OS world!"
times 510-($-$$) db 0 ; 填充剩下的空间,使生成的二进制代码恰好为512字节;表示将这个字节重复510-($-$$)遍。
dw 0xaa55 ; 结束标志

代码分析

1
2
3
4
5
6
7
8
9
10
$表示当前行被汇编后的地址
$$表示一个节(section)的开始处被汇编后的地址。在这里,我们的程序只有1个节,所以$$实际上就表示程序被编译后的开始地址。

从第10行开始为调用10hk号中断做准备(10h号中断是由BIOS对显示提供的服务),设置寄存器的值
AH:往屏幕中写入字符串
AL:写模式,bit 0(0位置零):写入字符串后更新光标; bit 1(1位置1):字符串中包括字符和属性;bit 2-7为保留位
BH: 页码
BL:如果字符串只包括characters,BL为字符串的属性
CX:字符串长度
DH,DL: 写字符串的起始列与行

3.生成启动镜像

1
2
nasm a.asm -o a.bin
dd if=a.bin of=a.img bs=512 count=1 conv=notrunc

4.使用QEMU引导软盘映像文件a.img

1
./qemu-system-i386 -hda /home/hys/code/6828/src/orange/ch1/a.img  # 根据自己情况适当修改文件路径

启动后效果如下:
image

至此一个简单的”操作系统”已经完成。


5.调试我们写的引导扇区代码

  • 启动qemu,等待gdb连接

    1
    qemu-system-i386 -hda /home/hys/code/6828/src/orange/ch1/a.img -gdb tcp::26000 -S
  • 启动gdbgdb -n -x .gdbinit,设置断点,观察寄存器的值
    p/x $cs显示寄存器cs的值

.gdbinit文件内容:设置gdb连接到时QEMU并调试早期启动的16位代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
set $lastcs = -1

define hook-stop
# There doesn't seem to be a good way to detect if we're in 16- or
# 32-bit mode, but we always run with CS == 8 in 32-bit mode.
if $cs == 8 || $cs == 27
if $lastcs != 8 && $lastcs != 27
set architecture i386
end
x/i $pc
else
if $lastcs == -1 || $lastcs == 8 || $lastcs == 27
set architecture i8086
end
# Translate the segment:offset into a physical address
printf "[%4x:%4x] ", $cs, $eip
x/i $cs*16+$eip
end
set $lastcs = $cs
end

echo + target remote localhost:26000\n
target remote localhost:26000
# If this fails, it's probably because your GDB doesn't support ELF.
# Look at the tools page at
# http://pdos.csail.mit.edu/6.828/2009/tools.html
# for instructions on building GDB with ELF support.
echo + symbol-file obj/kern/kernel\n
symbol-file obj/kern/kernel

gdb相关命令请查看http://visualgdb.com/gdbreference/commands/

Ref:
1.https://123xzy.github.io/2019/03/08/MIT-6-828-Lab-Guide/
2.Orange’S:一个操作系统的实现
3.qemu
4.gdb
5.Intel 80386 Reference Programmer’s Manual
7.lab1
8.Interrupts
9.https://en.wikipedia.org/wiki/INT_10H
10.http://visualgdb.com/gdbreference/commands/x