您的当前位置:首页正文

哈工大操作系统实验一:操作系统的引导

2024-11-22 来源:个人技术集锦


前言

做实验前一定要先拍个快照!!

操作系统实验环境的搭建请看如下链接(Ubuntu系统)







一.实验内容

两个部分

1.第一个部分

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

bootsect.s 能在屏幕上打印一段提示信息“XXX is booting…”,其中 XXX 是你给自己的操作系统起的名字,例如 LZJos、Sunix 等(可以上论坛上秀秀谁的 OS 名字最帅,也可以显示一个特色 logo,以表示自己操作系统的与众不同。)

2.第二个部分

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


二、实验内容1

这里需要修改的是字符串长度,即用需要输出的字符串长度替换 mov cx,#24 中的 24。要注意:除了我们设置的字符串 msg1 之外,还有三个换行 + 回车,一共是 6 个字符。比如这里 Hello OS world, my name is laoye! 的长度是 33,加上 6 后是 39,所以代码应该修改为 mov cx,#39。

步骤五:在此路径下打开终端

as86 -0 -a -o bootsect.o bootsect.s
ld86 -0 -s -o bootsect bootsect.o

其中 -0(注意:这是数字 0,不是字母 O)表示生成 8086 的 16 位目标程序,-a 表示生成与 GNU as 和 ld 部分兼容的代码,-s 告诉链接器 ld86 去除最后生成的可执行文件中的符号信息。

如果这两个命令没有任何输出,说明编译与链接都通过了。
没有报错的话,会出现以下.o文件

需要留意的文件是 bootsect 的文件大小是 544 字节,而引导程序必须要正好占用一个磁盘扇区,即 512 个字节。造成多了 32 个字节的原因是 ld86 产生的是 Minix 可执行文件格式,这样的可执行文件除了文本段、数据段等部分以外,还包括一个 Minix 可执行文件头部


步骤七:去掉这 32 个字节的文件头部,输入以下代码

dd bs=1 if=bootsect of=Image skip=32
cp ./Image ../Image
../../run

二、实验内容2

内容2的第一部分,向屏幕输出 Now we are in setup







步骤二:从第32行开始输入以下代码

 mov ax,#0x9000
 mov es,ax

 mov ax,#0x0300
 xor bh,bh
 int 0x10

mov cx,#25
mov bp,#msg2
mov bx,#0x0007
mov ax,#0x1301
int 0x10

步骤三:在第109行开始输入如下代码,保存退出

msg2:
	.byte 13,10
	.ascii "Now we are in setup!"
	.byte 13,10,13,10
make BootImage


步骤五:打个小补丁,修改build.c的代码

上面有 Error的原因是因为 make 根据 Makefile 的指引执行了 tools/build.c,它是为生成整个内核的镜像文件而设计的,没考虑我们只需要 bootsect.s 和 setup.s 的情况。它在向我们要 “系统” 的核心代码。为完成实验,接下来给它打个小补丁。

build.c 从命令行参数得到 bootsect、setup 和 system 内核的文件名,将三者做简单的整理后一起写入 Image。其中 system 是第三个参数(argv[3])。当 “make all” 或者 “makeall” 的时候,这个参数传过来的是正确的文件名,build.c 会打开它,将内容写入 Image。而 “make BootImage” 时,传过来的是字符串 “none”。所以,改造 build.c 的思路就是当 argv[3] 是"none"的时候,只写 bootsect 和 setup,忽略所有与 system 有关的工作,或者在该写 system 的位置都写上 “0”。

把第178行到第190行的内容全部注释掉





步骤6:重新运行,在路径为linux-0.11的终端下输入以下代码

make BootImage
../run







		INT 0x10功能0x03

描述:
在文本坐标下,读取光标各种信息
接受参数:
AH 0x03
BH 显示页码
返回值:
CH 光标的起始行
CL 光标的终止行
DH 行(Y 坐标)
DL 列(X 坐标)


使用BIOS中断 int 0x10 功能号 0x03 获取光标:

mov	ah,#0x03BIOS中断0x10功能号 ah=0x03 获取光标的位置
xor	bh,bh				! bh寄存器清0,bh寄存器存储带获取光标的页号0
int	0x10				!执行 BIOS 0x10号中断


		INT 0x10功能0x13


使用BIOS中断 int 0x10 功能号 0x13 显示字符串:

mov	ax,#SETUPSEG		! 将段寄存器 es 设置为 setup.s 开始位置
mov	es,ax
mov	bp,#MSG_SETUP		!es:bp 寄存器保存显示的字符串的地址

mov	cx,#25				! 字符串长度
mov	bx,#0x0007			! 页号 0,光标属性为停在字符串结尾处
                        ! 属性值,79都可以

mov	ax,#0x1301BIOS中断0x10功能号 ah=0x13 显示字符串
int	0x10				!执行 BIOS 0x10号中断




内容2的第二个部分,获取硬件参数



硬件参数在内存中的位置如下图所示






步骤一:进入setup.s文件,在第104行后添加如下代码并且后面所有步骤的代码都是从104行开始

  mov ax,#0x9020
  mov ds,ax
  mov es,ax
  / /此时的数据段从setup模块开始



步骤二:打印要输出的光标位置的提示信息,输入以下代码


mov ax,#0x0300
xor bh,bh
int 0x10

mov cx,#18
mov bp,#CURSOR_POSITION
mov bx,#0x0009 / / 或者是mov bx,#0x0007
mov ax,#0x1301
int 0x10

mov ax,#0x9000
mov ds,ax


步骤三:验证一下结果,在linux-0.11路径下输入以下代码

make BootImage
../run

结果正确


步骤四:显示硬件参数具体的信息,这是关键也是难点,提供以下两份原码,以及详细解释

小贴士

1.

2.

3.

4.

5.




源码一
print_hex1:
	mov	cx,#4			! 循环计数器
    mov	dx,[0]         
print_digit1:	
	rol	dx,#4			! 循环左移4位
	mov	ax,#0xe0f		! BIOS中断0x10功能号 ah=0x0E 显示一个字符
	and	al,dl			! 获取dl的低4比特值
	add	al,#0x30		! 数字加0x30
	cmp	al,#0x3a
	jl	outp1				
	add	al,#0x07		! 字母多加0x37
outp1:
   	int	0x10			! 执行 BIOS 0x10号中断
   	loop	print_digit1	! loop指令:cx减1,然后判断cx是否等于0

源码二
!显示数字 
	mov cx,#4 !416进制数 
	mov dx,[0] ! cursor  0x90000  
   PRINT_DIGIT1:
	rol dx,#4 !循环移位 高4位变低四位 
	mov ax,#0xe0f	!ah = 0e 显示一个字符(al)
	and al,dl	!DL的低四位 
	add al,#0x30	!转换成 ascii
	cmp al,#0x3A	!大于10? 
	jl OUTP1
	add al,#0x07	!大于10+7
  OUTP1:
	int 0x10
	loop PRINT_DIGIT1 ! CX--



不仅可以打印光标位置,其他硬件同理,也可打印

以扩展内存为例,输入以下代码



! 打印提示信息
mov ah,#0x03
xor bh,bh
int 0x10

mov cx,#
mov bp,#EXPAND_MENMORY
mov bx,#0x0007
mov ax,#0x1301
int 0x10


mov ax,#0x9000
mov ds,ax
mov es,ax

! 打印扩展内存
print_hex2:
     rol dx,#4
     mov ax,#0x0e0f
print_digit2:     
     and al,dl
     add al,#0x30
     cmp al,#0x3a
     jl output2
     add al,#0x07
output2:
     int 0x10
     loop print_digit2




步骤五:验证结果,linux-0.11路径下输入以下代码

make BootImage
../run


显示全文