哈工大操作系统实验1 引导

时间:2024-03-20 15:04:42

LINUX内核注释的笔记(第六章)

1

当PC电源打开后,CPU进入实模式,并从地址0XFFFF0执行,这个地址存放着ROM-BIOS。BIOS会执行某些系统检测,然后在物理地址0处开始初始化中断向量,此后,把启动设备第一扇区(就是磁盘引导扇区,512字节)的内容(bootsect)读入到0X7C00处,并跳转到这个地方。
bootsect程序把自己复制到内存0X90000处,并把setup程序读到内存0X90200处,其他部分(system)读到0X10000处,在这个期间系统显示"LOADING。。" 执行完后把控制权传递给setup
哈工大操作系统实验1 引导

2

哈工大操作系统实验1 引导

3

哈工大操作系统实验1 引导
哈工大操作系统实验1 引导
哈工大操作系统实验1 引导
哈工大操作系统实验1 引导

实验内容

修改Bootsect输出内容

这个基本不用动,就试一试输出字符串

        ! 首先读入光标位置
        mov    ah,#0x03        
        xor    bh,bh	!清零
        int    0x10	!ah=03 显示光标

        ! 显示字符串“LZJos is running...”
        mov    cx,#25            ! 要显示的字符串长度
        mov    bx,#0x0007        ! page 0, attribute 7 (normal)
        mov    bp,#msg1		!显示的串的地址为es:bp
        mov    ax,#0x1301        ! ah=13 al=01 写串并且光标跟着移动
        int    0x10

    inf_loop:
        jmp    inf_loop        ! 后面都不是正经代码了,得往回跳呀
        ! msg1处放置字符串

    msg1:
        .byte 13,10            ! 换行+回车
        .ascii "Taya is running..."
        .byte 13,10,13,10            ! 两对换行+回车
        !设置引导扇区标记0xAA55
        .org 510
    boot_flag:
        .word 0xAA55            ! 必须有它,才能引导

编译和连接bootsect.s

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

因为有Minix文件头部的原因需要执行如下命令删除

$ dd bs=1 if=bootsect of=Image skip=32

修改setup.s

这是实验的主要修改部分
修改他,显示 setup ing 和一些硬件的参数
首先汇编 显示数字的代码要看懂
其中用到的BIOS中断为INT 0x10,功能号0x0E(显示一个字符),即AH=0x0E,AL=要显示字符的ASCII码。

  !以16进制方式打印栈顶的16位数
    print_hex:
        mov    cx,#4         ! 4个十六进制数字
        mov    dx,(bp)     ! 将(bp)所指的值放入dx中,如果bp是指向栈顶的话
    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	!cx--
        ret

输出正在setup信息

!print mess
	mov ax,#SETUPSEG
	mov es,ax  !不能直接赋值给ES
	mov ah,#0x03 
	xor bh,bh
	int 0x10 ! 显示光标
	
	mov cx,#25 ! 长度
	mov bx,#0x0007 
	mov bp,#MSG_HELLO
	mov ax,#0x1301 !show es:bp
	int 0x10

获取数据的代码
就是把在内存相应位置的信息读出来 关键就是mov dx,[]

!print some datas about the hard ware:
!print the cursor position
	
	mov ah,#0x03
	xor bh,bh !清零BH 
	int 0x10	!ah=03 显示光标 
	
	mov cx,#25 !长度 
	mov bx,#0x0007 !页号  属性07为正常 ,其他可以改变颜色 
	mov bp,#MSG_CURSOR ! es:bp
	mov ax,#0x1301
	int 0x10 
	
	mov ax,#INITSEG
	mov ds,ax !设置数据段 
	
!显示数字 
	mov cx,#4 !4个16进制数 
	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--

修改完之后要删除一些代码,原因是后面的是加载SYSTEM模块的,我们这个实验不需要,如果不删除,会出错,导致一直在BOOTSECT循环

完整setup.s

!
!	setup.s		(C) 1991 Linus Torvalds
!
! setup.s is responsible for getting the system data from the BIOS,
! and putting them into the appropriate places in system memory.
! both setup.s and system has been loaded by the bootblock.
!
! This code asks the bios for memory/disk/other parameters, and
! puts them in a "safe" place: 0x90000-0x901FF, ie where the
! boot-block used to be. It is then up to the protected mode
! system to read them from there before the area is overwritten
! for buffer-blocks.
!

! NOTE! These had better be the same as in bootsect.s!

INITSEG  = 0x9000	! we move boot here - out of the way
SYSSEG   = 0x1000	! system loaded at 0x10000 (65536).
SETUPSEG = 0x9020	! this is the current segment

.globl begtext, begdata, begbss, endtext, enddata, endbss
.text
begtext:
.data
begdata:
.bss
begbss:
.text

entry start
	start:

!print mess
	mov ax,#SETUPSEG
	mov es,ax  !can't set es diretly,so we need ax
	mov ah,#0x03 
	xor bh,bh
	int 0x10 ! ah 03 xian shi guang biao
	
	mov cx,#25 !length
	mov bx,#0x0007 
	mov bp,#MSG_HELLO
	mov ax,#0x1301 !show es:bp
	int 0x10

! ok, the read went well so we get current cursor position and save it for
! posterity.

	mov	ax,#INITSEG	! this is done in bootsect already, but...
	mov	ds,ax
	mov	ah,#0x03	! read cursor pos
	xor	bh,bh
	int	0x10		! save it in known place, con_init fetches
	mov	[0],dx		! it from 0x90000.
! Get memory size (extended mem, kB)

	mov	ah,#0x88
	int	0x15
	mov	[2],ax

! Get video-card data:

	mov	ah,#0x0f
	int	0x10
	mov	[4],bx		! bh = display page
	mov	[6],ax		! al = video mode, ah = window width

! check for EGA/VGA and some config parameters

	mov	ah,#0x12
	mov	bl,#0x10
	int	0x10
	mov	[8],ax
	mov	[10],bx
	mov	[12],cx

! Get hd0 data

	mov	ax,#0x0000
	mov	ds,ax
	lds	si,[4*0x41]
	mov	ax,#INITSEG
	mov	es,ax
	mov	di,#0x0080
	mov	cx,#0x10
	rep
	movsb

! Get hd1 data

	mov	ax,#0x0000
	mov	ds,ax
	lds	si,[4*0x46]
	mov	ax,#INITSEG
	mov	es,ax
	mov	di,#0x0090
	mov	cx,#0x10
	rep
	movsb


	mov ax,#SETUPSEG
	mov es,ax
!print some datas about the hard ware:
!print the cursor position
	
	mov ah,#0x03
	xor bh,bh !清零BH 
	int 0x10	!ah=03 显示光标 
	
	mov cx,#25 !长度 
	mov bx,#0x0007 !页号  属性07为正常 ,其他可以改变颜色 
	mov bp,#MSG_CURSOR ! es:bp
	mov ax,#0x1301
	int 0x10 
	
	mov ax,#INITSEG
	mov ds,ax !设置数据段 
	
!显示数字 
	mov cx,#4 !4个16进制数 
	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--


! PRINT SIZE OF THE EXTENDED MEMORY
	mov ah,#0x03
	xor bh,bh
	int 0x10	
	
	mov cx,#37 
	mov bx,#0x0007 
	mov bp,#MSG_MEMORY 
	mov ax,#0x1301
	int 0x10 !gong neng biao

	mov ax,#INITSEG
	mov ds,ax 
	
	mov cx,#4
	mov dx,[2] #内存信息在0x90002 
   PRINT_DIGIT2:
	rol dx,#4 
	mov ax,#0xe0f	
	and al,dl	
	add al,#0x30	
	cmp al,#0x3A
	jl OUTP2
	add al,#0x07
   OUTP2:
	int 0x10
	loop PRINT_DIGIT2 ! 

!change the line
print_nl:
	mov ax,#0xe0d
	int 0x10
	mov al,0xa
	int 0x10

MSG_HELLO:
	.byte 13,10
	.ascii "we are in setup"
	.byte 13,10,13,10


MSG_CURSOR:
	.byte 13,10
	.ascii "the cursor position is:"
MSG_MEMORY:
	.byte 13,10
	.ascii "the size of extended memory is:"
.text
endtext:
.data
enddata:
.bss
endbss:

3 修改built.c

完成上面两个的时候,在Ubuntu下,进入linux-0.11目录后,使用下面命令(注意大小写):$ make BootImage
会出现错误信息

    Unable to open 'system'
    make: *** [BootImage] Error 1

这是因为built.c文件是一次编译三个文件即bootsect,setup,system,但是我们没有system,所以要修改。就是修改argv[3]的部分

if ((id=open(argv[3],O_RDONLY,0)) >= 0)                                        //就是打开文件的一个函数,失败的话会返回-1哦~
	{for (i=0 ; (c=read(id,buf,sizeof buf))>0 ; i+=c )
		if (write(1,buf,c)!=c)
			die("Write call failed");
	close(id);
	fprintf(stderr,"System is %d bytes.\n",i);
	if (i > SYS_SIZE*16)
		die("System is too big");}
	return(0);

原来是这样的:

if ((id=open(argv[3],O_RDONLY,0))<0)
		die("Unable to open 'system'");
//	if (read(id,buf,GCC_HEADER) != GCC_HEADER)
//		die("Unable to read header of 'system'");
//	if (((long *) buf)[5] != 0)
//		die("Non-GCC header of 'system'");
	for (i=0 ; (c=read(id,buf,sizeof buf))>0 ; i+=c )
		if (write(1,buf,c)!=c)
			die("Write call failed");
	close(id);
	fprintf(stderr,"System is %d bytes.\n",i);
	if (i > SYS_SIZE*16)
		die("System is too big");
	return(0);

弄了很久,但是我还是没有完全完成实验,大部分完成但是输出有些不对,不知道怎么修改

哈工大操作系统实验1 引导

实验楼 https://www.shiyanlou.com/courses/115
实验手册 https://hoverwinter.gitbooks.io/hit-oslab-manual/content/sy1_boot.html
别人写的报告 https://blog.csdn.net/wangyi_lin/article/details/6898837