lab1 实验准备
按照实验解压后进入oslab中,按照make编译。
cd /home/shiyanlou/oslab/
tar -zxvf hit-oslab-linux-20110823.tar.gz \
-C /home/shiyanlou/
./run
cd ./linux-0.11/
make all
make clean
.....
make all
运行脚本即可启动内核
调试
汇编级调试和C语言级调试
汇编级调试
# 确认在 oslab 目录下
$ cd ~/oslab/
# 运行脚本前确定已经关闭刚刚运行的 Bochs
$ ./dbg-asm
C语言级调试
需要两个终端并发
第一个进程终端
$ cd ~/oslab
$ ./dbg-c
第二个进程终端
$ cd ~/oslab
$ ./rungdb
文件交换
关闭bochs进程
$ cd ~/oslab/
# 启动挂载脚本
$ sudo ./mount-hdc
在hdc目录即可看见一模一样的文件系统
# 进入挂载到 Ubuntu 上的目录
$ cd ~/oslab/hdc
# 查看内容
$ ls -al
读写完毕后卸载
通过 sudo ./mount-hdc 进行挂载。
然后在 Ubuntu 的 ~/oslab/hdc/usr/root 目录下创建一个 xxx.c 文件,
sudo gedit ~/oslab/hdc/usr/root/xxx.c
再卸载文件系统sudo umount hdc,启动run脚本,在bochs输入ls命令
lab2 操作系统启动
bootsec.s改写
首先是显示要求的字符串
! 首先读入光标位置
mov ah,#0x03
xor bh,bh
int 0x10 !行->DH 列->DL
! 显示字符串 “YonglanOS is booting...”
! 要显示的字符串长度
mov cx,#36
mov bx,#0x0007 !黑底白字
mov bp,#msg1 ! 取msg地址给bp
! es:bp 是显示字符串的地址
! 相比与 linux-0.11 中的代码,需要增加对 es 的处理,因为原代码中在输出之前已经处理了 es
mov ax,#0x07c0
mov es,ax
mov ax,#0x1301
int 0x10
! 设置一个无限循环
inf_loop:
jmp inf_loop
Ubuntu 上先从终端进入 ~/oslab/linux-0.11/boot/ 目录。
Windows 上则先双击快捷方式 “MinGW32.bat”,将打开一个命令行窗口,当前目录是 oslab,用 cd 命令进入 linux-0.11\boot。
无论那种系统,都执行下面两个命令编译和链接 bootsect.s:
~/oslab/linux-0.11/boot/
$ as86 -0 -a -o bootsect.o bootsect.s
$ ld86 -0 -s -o bootsect bootsect.o
Ubuntu 下用 ls -l 可列出下面的信息:
-rw--x--x 1 root root 544 Jul 25 15:07 bootsect
-rw------ 1 root root 257 Jul 25 15:07 bootsect.o
-rw------ 1 root root 686 Jul 25 14:28 bootsect.s
其中 bootsect.o 是中间文件。bootsect 是编译、链接后的目标文件。
需要留意的文件是 bootsect 的文件大小是 544 字节,而引导程序必须要正好占用一个磁盘扇区,即 512 个字节。造成多了 32 个字节的原因是 ld86 产生的是 Minix 可执行文件格式
这样的可执行文件除了文本段、数据段等部分以外,还包括一个 Minix 可执行文件头部,它的结构如下:
struct exec {
unsigned char a_magic[2]; //执行文件魔数
unsigned char a_flags;
unsigned char a_cpu; //CPU标识号
unsigned char a_hdrlen; //头部长度,32字节或48字节
unsigned char a_unused;
unsigned short a_version;
long a_text; long a_data; long a_bss; //代码段长度、数据段长度、堆长度
long a_entry; //执行入口地址
long a_total; //分配的内存总量
long a_syms; //符号表大小
};
算一算:6 char(6 字节)+ 1 short(2 字节) + 6 long(24 字节)= 32,正好是 32 个字节,去掉这 32 个字节后就可以放入引导扇区了(这是 tools/build.c 的用途之一)。
对于上面的 Minix 可执行文件,其 a_magic[0]=0x01,a_magic[1]=0x03,a_flags=0x10(可执行文件),a_cpu=0x04(表示 Intel i8086/8088,如果是 0x17 则表示 Sun 公司的 SPARC),所以 bootsect 文件的头几个字节应该是 01 03 10 04。为了验证一下,Ubuntu 下用命令“hexdump -C bootsect”可以看到:
00000000 01 03 10 04 20 00 00 00 00 02 00 00 00 00 00 00 |.... ...........|
00000010 00 00 00 00 00 00 00 00 00 82 00 00 00 00 00 00 |................|
00000020 b8 c0 07 8e d8 8e c0 b4 03 30 ff cd 10 b9 17 00 |.........0......|
00000030 bb 07 00 bd 3f 00 b8 01 13 cd 10 b8 00 90 8e c0 |....?...........|
00000040 ba 00 00 b9 02 00 bb 00 02 b8 04 02 cd 13 73 0a |..............s.|
00000050 ba 00 00 b8 00 00 cd 13 eb e1 ea 00 00 20 90 0d |............. ..|
00000060 0a 53 75 6e 69 78 20 69 73 20 72 75 6e 6e 69 6e |.Sunix is runnin|
00000070 67 21 0d 0a 0d 0a 00 00 00 00 00 00 00 00 00 00 |g!..............|
00000080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
00000220
去掉这 32 个字节后,将生成的文件拷贝到 linux-0.11 目录下,并一定要命名为“Image”(注意大小写)。然后就“run”吧!
接下来干什么呢?是的,要去掉这 32 个字节的文件头部(tools/build.c 的功能之一就是这个)!随手编个小的文件读写程序都可以去掉它。不过,懒且聪明的人会在 Ubuntu 下用命令:
$ dd bs=1 if=bootsect of=Image skip=32
生成的 Image 就是去掉文件头的 bootsect。
Windows 下可以用 UltraEdit 直接删除(选中这 32 个字节,然后按 Ctrl+X)。
去掉这 32 个字节后,将生成的文件拷贝到 linux-0.11 目录下,并一定要命名为“Image”(注意大小写)。然后就“run”吧!
bootsec.s读入setup.s
显示字符的功能直接复制bootsec.s上的内容进行修改
```c
! 首先读入光标位置
mov ah,#0x03
xor bh,bh
int 0x10 !行->DH 列->DL
! 显示字符串 “"Hello OS world, my name is JYL"”
! 要显示的字符串长度
mov cx,#36
mov bx,#0x0007 !黑底白字
mov bp,#msg1 ! 取msg地址给bp
! es:bp 是显示字符串的地址
! 相比与 linux-0.11 中的代码,需要增加对 es 的处理,因为原代码中在输出之前已经处理了 es
mov ax,#0x07c0
mov es,ax
mov ax,#0x1301
int 0x10
接下来,读入setup.s
load_setup:
! 设置驱动器和磁头(drive 0, head 0): 软盘 0 磁头
mov dx,#0x0000
! 设置扇区号和磁道(sector 2, track 0): 0 磁头、0 磁道、2 扇区
mov cx,#0x0002
! 设置读入的内存地址:BOOTSEG+address = 512,偏移512字节
mov bx,#0x0200
! 设置读入的扇区个数(service 2, nr of sectors),
! SETUPLEN是读入的扇区个数,Linux 0.11 设置的是 4,
! 我们不需要那么多,我们设置为 2(因此还需要添加变量 SETUPLEN=2)
mov ax,#0x0200+SETUPLEN
! 应用 0x13 号 BIOS 中断读入 2 个 setup.s扇区
int 0x13
! 读入成功,跳转到 ok_load_setup: ok - continue,int 0x13出错会置位CF
jnc ok_load_setup
! 软驱、软盘有问题才会执行到这里。我们的镜像文件比它们可靠多了
mov dx,#0x0000
! 否则复位软驱 reset the diskette
mov ax,#0x0000
int 0x13
! 重新循环,再次尝试读取
jmp load_setup
ok_load_setup:
! 接下来要干什么?当然是跳到 setup 执行。
! 要注意:我们没有将 bootsect 移到 0x9000,因此跳转后的段地址应该是 0x7ce0
! 即我们要设置 SETUPSEG=0x07e0
接下来是一些数据
msg1:
.byte 13,10
.ascii "Hello OS world, my name is JYL"
.byte 13,10,13,10
.org 510
boot_flag:
.word 0xAA55