哈工大 操作系统 lab1 操作系统的引导解答

您所在的位置:网站首页 linux和oslab 哈工大 操作系统 lab1 操作系统的引导解答

哈工大 操作系统 lab1 操作系统的引导解答

2024-05-17 02:31| 来源: 网络整理| 查看: 265

实验目的 熟悉hit-oslab实验环境; 建立对操作系统引导过程的深入认识; 掌握操作系统的基本开发过程; 能对操作系统代码进行简单的控制,揭开操作系统的神秘面纱。 实验内容

此次实验的基本内容是:

阅读《Linux内核完全注释》的第6章,对计算机和Linux 0.11的引导过程进行初步的了解; 按照下面的要求改写0.11的引导程序bootsect.s 有兴趣同学可以做做进入保护模式前的设置程序setup.s。

改写bootsect.s主要完成如下功能:

bootsect.s能在屏幕上打印一段提示信息“XXX is booting...”,其中XXX是你给自己的操作系统起的名字,例如LZJos、Sunix等

改写setup.s主要完成如下功能:

bootsect.s能完成setup.s的载入,并跳转到setup.s开始地址执行。而setup.s向屏幕输出一行"Now we are in SETUP"。 setup.s能获取至少一个基本的硬件参数(如内存参数、显卡参数、硬盘参数等),将其存放在内存的特定地址,并输出到屏幕上。 setup.s不再加载Linux内核,保持上述信息显示在屏幕上即可。 实验过程 1 bootsect.s在屏幕上打印一段提示信息

linux0.11源码中便有,改改即可。

核心代码如下:

! Print some inane message ok_load_setup: mov ah,#0x03 ! read cursor pos xor bh,bh int 0x10 mov cx,#23 mov bx,#0x0007 ! page 0, attribute 7 (normal) mov bp,#msg1 mov ax,#0x1301 ! write string, move cursor int 0x10 msg1: .byte 13,10 .ascii "COS is booting..." .byte 13,10,13,10 .org 508 root_dev: .word ROOT_DEV boot_flag: .word 0xAA55 2 bootsect.s完成setup.s的载入,并跳转到setup.s开始地址执行

首先是需要知道内存中的几个模块,比如boot、setup、system;

image-20211205110121853

系统上电后各模块之间的执行顺序:

image-20211205110302115

系统上电后,会将bootsec.s加载入0x7C00位置 bootsec.s将自己移动到0x90000 加载setup.s入内存,加载system入0x10000处,然后跳转至setup.s中执行 setup.s加载一些硬件参数 将系统移动至0x0000处,跳转至system中的head.s中执行

image-20211205110339803

需要在bootsect.s中实现跳转到setup.s中执行:

SETUPLEN = 4 ! nr of setup-sectors BOOTSEG = 0x07c0 ! original address of boot-sector INITSEG = 0x9000 ! we move boot here - out of the way SETUPSEG = 0x9020 ! setup starts here SYSSEG = 0x1000 ! system loaded at 0x10000 (65536). ENDSEG = SYSSEG + SYSSIZE ! where to stop loading ! ROOT_DEV: 0x000 - same type of floppy as boot. ! 0x301 - first partition on first drive etc ROOT_DEV = 0x306 ! move BOOTSEG -> INITSEG entry _start _start: mov ax,#BOOTSEG mov ds,ax mov ax,#INITSEG mov es,ax mov cx,#256 sub si,si sub di,di rep movw jmpi go,INITSEG go: mov ax,cs mov ds,ax mov es,ax ! load setup.s load_setup: mov dx,#0x0000 ! drive 0, head 0 mov cx,#0x0002 ! sector 2, track 0 mov bx,#0x0200 ! address = 512, in INITSEG mov ax,#0x0200+SETUPLEN ! service 2, nr of sectors int 0x13 ! read it jnc ok_load_setup ! ok - continue mov dx,#0x0000 mov ax,#0x0000 ! reset the diskette int 0x13 j load_setup ! jump to setup.s jmpi 0,SETUPSEG

然后在setup.s中显示已经跳转到setup.s中了,如下:(一定要记得重设ds数据段的寄存器,因为msg是在0x90200开始的数据段上的)

entry _start _start: init_ds_es: mov ax,cs mov ds,ax mov es,ax ! Print in begining of setup.s print_cur: mov ah,#0x03 ! read cursor pos xor bh,bh int 0x10 mov cx,#28 mov bx,#0x0007 ! page 0, attribute 7 (normal) mov bp,#msg1 mov ax,#0x1301 ! write string, move cursor int 0x10 msg1: .ascii "Now we are in SETUP..." .byte 13,10,13,10 3 setup.s获取硬件参数,将其存放在内存的特定地址,并输出到屏幕上 3.1 获取光标位置

使用bios的0x10号中断实现,ah是功能选择,结果放在dx中,最后将结果放入0x90000。

! get cursor pos mov ax,#INITSEG mov ds,ax ! set ds=0x9000 mov ah,#0x03 ! get cursor pos xor bh,bh int 0x10 ! interrupt mov [0],dx ! write cursor pos to 0x90000.

打印:

print_cursor_pos: mov ah,#0x03 ! read cursor pos xor bh,bh int 0x10 mov cx,#10 mov bx,#0x0007 ! page 0, attribute 7 (normal) mov bp,#cursor mov ax,#0x1301 ! write string, move cursor int 0x10 mov ax,[0] call print_hex call print_nl 3.2 获取内存大小

同上,利用bios的0x15号中断:

! get memory size mov ah,#0x88 int 0x15 mov [2],ax

打印:

print_memmory_size: mov ah,#0x03 ! read cursor pos xor bh,bh int 0x10 mov cx,#14 mov bx,#0x0007 ! page 0, attribute 7 (normal) mov bp,#memory_size mov ax,#0x1301 ! write string, move cursor int 0x10 mov ax,[2] call print_hex 3.3 获取硬盘参数 ! 从0x41处拷贝16个字节(磁盘参数表) mov ax,#0x0000 mov ds,ax lds si,[4*0x41] mov ax,#INITSEG mov es,ax mov di,#0x0004 mov cx,#0x10 rep ! for i in 16: movsb

打印:

print_hd_info: ! Cylinders mov ah,#0x03 ! read cursor pos xor bh,bh int 0x10 mov cx,#16 mov bx,#0x0007 ! page 0, attribute 7 (normal) mov bp,#hdinfo mov ax,#0x1301 ! write string, move cursor int 0x10 mov ax,[4] call print_hex call print_nl ! head mov ah,#0x03 ! read cursor pos xor bh,bh int 0x10 mov cx,#10 mov bx,#0x0007 ! page 0, attribute 7 (normal) mov bp,#head mov ax,#0x1301 ! write string, move cursor int 0x10 xor ax, ax mov al,[4+2] call print_hex call print_nl ! sect mov ah,#0x03 ! read cursor pos xor bh,bh int 0x10 mov cx,#10 mov bx,#0x0007 ! page 0, attribute 7 (normal) mov bp,#sect mov ax,#0x1301 ! write string, move cursor int 0x10 xor ax, ax mov al,[0x4+0x0E] call print_hex call print_nl 4 setup.s不再加载Linux内核,保持上述信息显示在屏幕上即可

上述工作完成后,直接死循环即可:

dead_loop: jmp dead_loop 5 完整代码

bootsec.s:

! ! SYS_SIZE is the number of clicks (16 bytes) to be loaded. ! 0x3000 is 0x30000 bytes = 196kB, more than enough for current ! versions of linux ! SYSSIZE = 0x3000 ! ! bootsect.s (C) 1991 Linus Torvalds ! ! bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves ! iself out of the way to address 0x90000, and jumps there. ! ! It then loads 'setup' directly after itself (0x90200), and the system ! at 0x10000, using BIOS interrupts. ! ! NOTE! currently system is at most 8*65536 bytes long. This should be no ! problem, even in the future. I want to keep it simple. This 512 kB ! kernel size should be enough, especially as this doesn't contain the ! buffer cache as in minix ! ! The loader has been made as simple as possible, and continuos ! read errors will result in a unbreakable loop. Reboot by hand. It ! loads pretty fast by getting whole sectors at a time whenever possible. .globl begtext, begdata, begbss, endtext, enddata, endbss .text begtext: .data begdata: .bss begbss: .text SETUPLEN = 4 ! nr of setup-sectors BOOTSEG = 0x07c0 ! original address of boot-sector INITSEG = 0x9000 ! we move boot here - out of the way SETUPSEG = 0x9020 ! setup starts here SYSSEG = 0x1000 ! system loaded at 0x10000 (65536). ENDSEG = SYSSEG + SYSSIZE ! where to stop loading ! ROOT_DEV: 0x000 - same type of floppy as boot. ! 0x301 - first partition on first drive etc ROOT_DEV = 0x306 ! move BOOTSEG -> INITSEG entry _start _start: mov ax,#BOOTSEG mov ds,ax mov ax,#INITSEG mov es,ax mov cx,#256 sub si,si sub di,di rep movw jmpi go,INITSEG go: mov ax,cs mov ds,ax mov es,ax ! load setup.s load_setup: mov dx,#0x0000 ! drive 0, head 0 mov cx,#0x0002 ! sector 2, track 0 mov bx,#0x0200 ! address = 512, in INITSEG mov ax,#0x0200+SETUPLEN ! service 2, nr of sectors int 0x13 ! read it jnc ok_load_setup ! ok - continue mov dx,#0x0000 mov ax,#0x0000 ! reset the diskette int 0x13 j load_setup ! Print some inane message ok_load_setup: mov ah,#0x03 ! read cursor pos xor bh,bh int 0x10 mov cx,#23 mov bx,#0x0007 ! page 0, attribute 7 (normal) mov bp,#msg1 mov ax,#0x1301 ! write string, move cursor int 0x10 ! jump to setup.s jmpi 0,SETUPSEG sectors: .word 0 msg1: .byte 13,10 .ascii "COS is booting..." .byte 13,10,13,10 .org 508 root_dev: .word ROOT_DEV boot_flag: .word 0xAA55 .text endtext: .data enddata: .bss endbss:

setup.s:

.globl begtext, begdata, begbss, endtext, enddata, endbss .text begtext: .data begdata: .bss begbss: .text SETUPLEN = 4 ! nr of setup-sectors BOOTSEG = 0x07c0 ! original address of boot-sector INITSEG = 0x9000 ! we move boot here - out of the way SETUPSEG = 0x9020 ! setup starts here SYSSEG = 0x1000 ! system loaded at 0x10000 (65536). ENDSEG = SYSSEG + SYSSIZE ! where to stop loading ! ROOT_DEV: 0x000 - same type of floppy as boot. ! 0x301 - first partition on first drive etc ROOT_DEV = 0x306 entry _start _start: init_ds_es: mov ax,cs mov ds,ax mov es,ax ! Print in begining of setup.s print_cur: mov ah,#0x03 ! read cursor pos xor bh,bh int 0x10 mov cx,#28 mov bx,#0x0007 ! page 0, attribute 7 (normal) mov bp,#msg1 mov ax,#0x1301 ! write string, move cursor int 0x10 ! get cursor pos mov ax,#INITSEG mov ds,ax ! set ds=0x9000 mov ah,#0x03 ! get cursor pos xor bh,bh int 0x10 ! interrupt mov [0],dx ! write cursor pos to 0x90000. ! get memory size mov ah,#0x88 int 0x15 mov [2],ax ! 从0x41处拷贝16个字节(磁盘参数表) mov ax,#0x0000 mov ds,ax lds si,[4*0x41] mov ax,#INITSEG mov es,ax mov di,#0x0004 mov cx,#0x10 rep ! for i in 16: movsb reset_ds_es: mov ax,#INITSEG mov ds,ax mov ax,#SETUPSEG mov es,ax print_cursor_pos: mov ah,#0x03 ! read cursor pos xor bh,bh int 0x10 mov cx,#10 mov bx,#0x0007 ! page 0, attribute 7 (normal) mov bp,#cursor mov ax,#0x1301 ! write string, move cursor int 0x10 mov ax,[0] call print_hex call print_nl print_memmory_size: mov ah,#0x03 ! read cursor pos xor bh,bh int 0x10 mov cx,#14 mov bx,#0x0007 ! page 0, attribute 7 (normal) mov bp,#memory_size mov ax,#0x1301 ! write string, move cursor int 0x10 mov ax,[2] call print_hex print_hd_info: ! Cylinders mov ah,#0x03 ! read cursor pos xor bh,bh int 0x10 mov cx,#16 mov bx,#0x0007 ! page 0, attribute 7 (normal) mov bp,#hdinfo mov ax,#0x1301 ! write string, move cursor int 0x10 mov ax,[4] call print_hex call print_nl ! head mov ah,#0x03 ! read cursor pos xor bh,bh int 0x10 mov cx,#10 mov bx,#0x0007 ! page 0, attribute 7 (normal) mov bp,#head mov ax,#0x1301 ! write string, move cursor int 0x10 xor ax, ax mov al,[4+2] call print_hex call print_nl ! sect mov ah,#0x03 ! read cursor pos xor bh,bh int 0x10 mov cx,#10 mov bx,#0x0007 ! page 0, attribute 7 (normal) mov bp,#sect mov ax,#0x1301 ! write string, move cursor int 0x10 xor ax, ax mov al,[0x4+0x0E] call print_hex call print_nl dead_loop: jmp dead_loop ! 以16进制方式打印栈顶的16位数, AX print_hex: mov cx,#4 ! 4个十六进制数字 mov dx,ax ! 将ax所指的值放入dx中 print_digit: rol dx,#4 ! 循环以使低4比特用上 !! 取dx的高4比特移到低4比特处。 mov ax,#0xe0f ! ah = 请求的功能值,al = 半字节(4个比特)掩码。 and al,dl ! 取dl的低4比特值。 add al,#0x30 ! 给al数字加上十六进制0x30 cmp al,#0x3a jl outp !是一个不大于十的数字 add al,#0x07 !是a~f,要多加7 outp: int 0x10 loop print_digit ret ! print \n print_nl: mov ax,#0xe0d ! CR int 0x10 mov al,#0xa ! LF int 0x10 ret msg1: .ascii "Now we are in SETUP..." .byte 13,10,13,10 cursor: .ascii "cursor: 0x" memory_size: .ascii "memory_size:0x " hdinfo: .ascii "KB" .byte 13,10 .ascii "Cylinders:0x" head: .ascii "Headers:0x" sect: .ascii "Secotrs:0x" .org 508 root_dev: .word ROOT_DEV boot_flag: .word 0xAA55 .text endtext: .data enddata: .bss endbss:

使用make BootImage编译不过去,是要改一下tools/build.c:

判断system模块有没有,没有直接跳过后边读取即可:

if (strcmp(argv[3], "none") == 0) { return 0; }

加入位置如下:

image-20211205112753847

实验结果

编译:

image-20211205113026925

运行结果:

image-20211205113131567

查看bochs配置文件:

romimage: file=$OSLAB_PATH/bochs/BIOS-bochs-latest megs: 16 vgaromimage: file=$OSLAB_PATH/bochs/vgabios.bin floppya: 1_44="$OSLAB_PATH/linux-0.11/Image", status=inserted ata0-master: type=disk, path="$OSLAB_PATH/hdc-0.11.img", mode=flat, cylinders=204, heads=16, spt=38 boot: a log: $OSLAB_PATH/bochsout.txt keyboard: type=mf, serial_delay=200, paste_delay=100000 cpu: count=1, ips=4000000 mouse: enabled=0 private_colormap: enabled=0 fullscreen: enabled=0 screenmode: name="sample"

其中有cylinders=204, heads=16, spt=38,和系统输出的获取到的参数是一样的,因此本次实验是成功的!

reference

[1] 实验指导书



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3