哈工大 操作系统 lab1 操作系统的引导解答 |
您所在的位置:网站首页 › linux和oslab › 哈工大 操作系统 lab1 操作系统的引导解答 |
实验目的
熟悉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; 系统上电后各模块之间的执行顺序: 需要在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; }加入位置如下: 编译: 运行结果: 查看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 |