【操作系统】实验楼实验2-操作系统的启动

实验2 ——操作系统的启动

载入环境

cd /home/shiyanlou/oslab/
tar -zxvf hit-oslab-linux-20110823.tar.gz \
  -C /home/shiyanlou/
ls -al
cd ./linux-0.11/
cd ./boot/

​ 首先进入oslab文件夹,找到目标压缩包并解压,查看是否解压成功后进入系统。

改写bootsect.s并显示

mv bootsect.s bootsect-old.s
gedit bootsect.s

​ 创建一个新的.s文件,用于显示新值并对bootsect.s文件进行写入

​ 图1 编写bootsect.s文件

​ 具体代码如下:

entry _start
_start:
    mov ah,#0x03
    xor bh,bh
    int 0x10
    mov cx,#36
    mov bx,#0x0007
    mov bp,#msg1
    mov ax,#0x07c0
    mov es,ax
    mov ax,#0x1301
    int 0x10
inf_loop:
    jmp inf_loop
msg1:
    .byte   13,10
    .ascii  "Hello OS world, my name is LZJ"
    .byte   13,10,13,10
.org 510
boot_flag:
    .word   0xAA55

​ 在这段代码中的核心部分是修改参数,首先用int找到并读入光标位置,预先设定并写出要展示的字符串长度。mgs1是我们设定的字符串,除此之外还需要考虑三个换行与回车,一共六个字符。输出语句的长度为30,总计36,故修改为mov cx,#36。设置一个循环,然后修改输出的字符串,最后为了保证boot_flag在最后两个字节,修改.org为510,同时设置引导扇区标记0xAA55引导。

​ 接下来,让编写完成的bootsect.s 代码在开发环境中编译,并将编译后的目标文件做成 Image 文件:

as86 -0 -a -o bootsect.o bootsect.s    
ld86 -0 -s -o bootsect bootsect.o
dd bs=1 if=bootsect of=Image skip=32

​ 首先生成与GNU as和ld部分兼容的代码,然后用ld886去除最后生成的可执行文件中的符号信息,最后把32个字节的文件头部去掉,便可以放入引导扇区。

​ 最后将处理完成的文件重命名,并输出结果:

cp ./Image ../Image
../../run

​ 将刚刚生成的 Image 复制到 linux-0.11 目录下,并执行oslab目录中的 run 脚本。
在这里插入图片描述
​ 图3 改写bootsect.s显示图

bootsect.s 读入 setup

​ 首先将原来的setup.s重命名,并编写一个新的setup.s用于输出信息。

entry _start
    start:
		mov ah,#0x03
        xor bh,bh
        int 0x10
        mov cx,#25
        mov bx,#0x0007
        mov bp,#msg2
        mov ax,cs
        mov es,ax
        mov ax,#0x1301
        int 0x10
inf_loop:
	jmp inf_loop
msg2:
	.byte 13,10
    .ascil "Now we are in SETUP"
    .byte 13,10,13,10
.org 510
boot_flag:
	.word 0xAA55

​ 此处设立新的字符串msg2,并且修改es的值使其可以使用cs(以ax为中间变量)。最后就是修改此处需要输出的字符。

​ 在对setup.s进行改写之后还需要对bootsect.s进行修改,载入setup.s的关键代码使其可以启动setup.s。

SETUPLEN=2
SETUPSEG=0x07e0
entry _start
_start:
    mov ah,#0x03
    xor bh,bh
    int 0x10
    mov cx,#36
    mov bx,#0x0007
    mov bp,#msg1
    mov ax,#0x07c0
    mov es,ax
    mov ax,#0x1301
    int 0x10
load_setup:
    mov dx,#0x0000
    mov cx,#0x0002
    mov bx,#0x0200
    mov ax,#0x0200+SETUPLEN
    int 0x13
    jnc ok_load_setup
    mov dx,#0x0000
    mov ax,#0x0000
    int 0x13
    jmp load_setup
ok_load_setup:
    jmpi    0,SETUPSEG
msg1:
    .byte   13,10
    .ascii  "Hello OS world, my name is ZJC"
    .byte   13,10,13,10
.org 510
boot_flag:
    .word   0xAA55

​ 在这里设置了驱动、磁盘以及读入的内存地址,由于我们需要两个扇区大小内存,设置SETUPLEN=2。我们没有将bootsect移动到0x9000,因此跳转后的段地址为0x07e0。为了跳到setup进行执行,设置SETUPSEG为0x07e0。

​ _start部分为原版bootsect.s中的代码,而我们需要在其中添加载入setup.s的关键代码:load_setup。分别设置扇区号、磁道、读入的内存地址、扇区个数(其中SETUPLEN扇区个数,由前可知设置为2),接着利用0x13号BIOS中断读入2个setup.s扇区。如果成功跳转则进入ok_load_setup,跳转到SETUPSEG位置处执行setup。后续程序与原版bootsect一致。

在这里插入图片描述

​ 图4 改写bootsect.s截图

​ 现在我们获得了setup.s和新的bootsect.s,需要对这两个文件进行编译.为了提高效率我们使用Makefile进行编译,在这之前需要对tools/build.c文件进行修改(正常情况下该文件生成整个系统内核镜像)。修改的目的是使argv[3]是“none"的时候,只写bootsect和setup,忽略所有与system有关的工作,或者在该写system的位置都写上0。把build.c的全局变量注释掉即可。

在这里插入图片描述

​ 图5 改写build.c截图

​ 之后再进行编译,输出结果如图:

在这里插入图片描述

​ 图6 setup显示成功截图

​ 实验成功。

setup获取硬件参数及显示硬件参数

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
movsb

​ setup.s 将获得硬件参数放在内存的 0x90000 处,用 ah=#0x03 调用 0x10 中断可以读出光标的位置,用 ah=#0x88 调用0x15 中断可以读出内存的大小。 int 0x41 的中断向量位置存放第一个硬盘的基本参数表。这部分就是显示硬件参数的关键代码。

setup正确显示硬件参数

INITSEG  = 0x9000entry _start_start:    mov ah,#0x03    xor bh,bh    int 0x10    mov cx,#25    mov bx,#0x0007    mov bp,#msg2    mov ax,cs    mov es,ax    mov ax,#0x1301    int 0x10(...)    mov dx,[12]    call    print_hexinf_loop:    jmp inf_loopprint_hex:    mov    cx,#4print_digit:    rol    dx,#4    mov    ax,#0xe0f    and    al,dl    add    al,#0x30    cmp    al,#0x3a    jl     outp    add    al,#0x07outp:    int    0x10    loop   print_digit    retprint_nl:    mov    ax,#0xe0d     ! CR    int    0x10    mov    al,#0xa     ! LF    int    0x10    retmsg2:    .byte 13,10    .ascii "NOW we are in SETUP"    .byte 13,10,13,10msg_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 510boot_flag:    .word 0xAA55

​ 将原二进制数每 4 位划成一组,按组求对应的 ASCII 码并让显示器显示。调用BIOS的INT 0x10中断读出光标位置,即AH=0x0E,其中AL为要显示的字符的ASCII码,依次调用出需要显示的部件。接着调用 print_bx 和 print_nl将获得硬件参数打印到屏幕上。

​ 结果截图如下:
在这里插入图片描述

​ 图7 setup显示硬件参数结果截图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值