本次实验是在Ubuntu 20.04下进行的。首先是bootsect.s代码。如下所示:
entry _start ;entry告诉链接器从这里开始执行
_start:
;读取光标位置,BIOS的0x10中断的0x03功能是读取光标位置。
mov ah,#0x03
xor bh,bh
int 0x10
mov cx,#23 ;字符串长度
mov bx,#0x000c ;显示红色的字符串
mov bp,#msg1 ;向屏幕写入的字符串
mov ax,#0x07c0
mov es,ax ;给es写入0x07c0
mov ax,#0x1301 ;向屏幕写字符串并移动光标到末尾
int 0x10 ;BIOS的0x10中断的0x13功能的0x01子功能
inf_loop:
jmp inf_loop ;死循环
msg1:
.byte 13,10 ;回车换行
.ascii "Zy's os is booting..."
.byte 13,10
.org 510 ;之后的语句从510开始
boot_flag:
.word 0xAA55 ;磁盘引导标志0xAA55
接下来进行汇编,链接。使用如下的命令:
$ as86 -0 -a -o bootsect.o bootsect.s
$ ld86 -0 -s -o bootsect bootsect.o
如果你编译的时候as86提示as: error reading input.那么大概率是你所使用的编辑器的问题,这时候你只需要用vi打开bootsect.s,然后保存,就可以了。
经过上面的编译之后,生成了bootsect文件,然后使用ls -l命令查看大小,就会发现它是544kb,而不是512kb。引导程序必须要正好占用一个磁盘扇区,即 512 个字节。造成多了 32 个字节的原因是 ld86 产生的是 Minix 可执行文件格式。在Ubuntu下可以使用如下的命令去除这多余的32字节。
$ dd bs=1 if=bootsect of=Image skip=32
此时会生成一个名为Image的文件,它的大小刚好是512KB,我们移动他到linux-0.11目录下
可以看到Image是512字节大小,然后在执行oslab目录下的run即可看到bochs界面输出红色的一串字符串。如下所示:
之后的setup.s代码如下所示:
INITSEG = 0x9000
entry _start
_start:
! Print "NOW we are in SETUP"
;利用BIOS中断,读取光标所在位置
mov ah,#0x03
xor bh,bh
int 0x10
mov cx,#25 ;25个字符
mov bx,#0x0007 ;字符串属性
mov bp,#msg2 ;msg2就是NOW we are in SETUP这串字符串
mov ax,cs
mov es,ax
mov ax,#0x1301 ;向屏幕写字符串并移动光标到末尾
int 0x10
mov ax,cs
mov es,ax
! init ss:sp ;初始化栈指针为0x9ff00
mov ax,#INITSEG
mov ss,ax
mov sp,#0xFF00
! Get Params
mov ax,#INITSEG
mov ds,ax
mov ah,#0x03
xor bh,bh
int 0x10
mov [0],dx
mov ah,#0x88
int 0x15
mov [2],ax
mov ax,#0x0000
mov ds,ax
lds si,[4*0x41]
mov ax,#INITSEG
mov es,ax
mov di,#0x0004
mov cx,#0x10
rep
movsbss
! Be Ready to Print
mov ax,cs
mov es,ax
mov ax,#INITSEG
mov ds,ax
! Cursor Position
mov ah,#0x03
xor bh,bh
int 0x10
mov cx,#18
mov bx,#0x0007
mov bp,#msg_cursor
mov ax,#0x1301
int 0x10
mov dx,[0]
call print_hex
! Memory Size
mov ah,#0x03
xor bh,bh
int 0x10
mov cx,#14
mov bx,#0x0007
mov bp,#msg_memory
mov ax,#0x1301
int 0x10
mov dx,[2]
call print_hex
! Add KB
mov ah,#0x03
xor bh,bh
int 0x10
mov cx,#2
mov bx,#0x0007
mov bp,#msg_kb
mov ax,#0x1301
int 0x10
! Cyles
mov ah,#0x03
xor bh,bh
int 0x10
mov cx,#7
mov bx,#0x0007
mov bp,#msg_cyles
mov ax,#0x1301
int 0x10
mov dx,[4]
call print_hex
! Heads
mov ah,#0x03
xor bh,bh
int 0x10
mov cx,#8
mov bx,#0x0007
mov bp,#msg_heads
mov ax,#0x1301
int 0x10
mov dx,[6]
call print_hex
! Secotrs
mov ah,#0x03
xor bh,bh
int 0x10
mov cx,#10
mov bx,#0x0007
mov bp,#msg_sectors
mov ax,#0x1301
int 0x10
mov dx,[12]
call print_hex
inf_loop:
jmp inf_loop
print_hex:
mov cx,#4
print_digit:
rol dx,#4
mov ax,#0xe0f
and al,dl
add al,#0x30
cmp al,#0x3a
jl outp
add al,#0x07
outp:
int 0x10
loop print_digit
ret
print_nl:
mov ax,#0xe0d ! CR
int 0x10
mov al,#0xa ! LF
int 0x10
ret
msg2:
.byte 13,10,13,10
.ascii "NOW we are in SETUP"
.byte 13,10
msg_cursor:
.byte 13,10
.ascii "Cursor position:"
msg_memory:
.byte 13,10
.ascii "Memory Size:"
msg_cyles:
.byte 13,10
.ascii "Cyls:"
msg_heads:
.byte 13,10
.ascii "Heads:"
msg_sectors:
.byte 13,10
.ascii "Sectors:"
msg_kb:
.ascii "KB"
.org 510
boot_flag:
.word 0xAA55
关于BIOS的int 0x10中断,网上有很多资料介绍了如何使用,感兴趣的可以自己去看看。之后,可以参考赵炯博士写的《Linux内核完全注释》里有关tools工具的介绍。在这里,我们注释掉下图中的部分。
然后在linux-0.11目录下使用make BootImage命令即可。然后在oslab目录下运行run,即可看到如下界面。
至此,实验1完成。