LINUX内核注释的笔记(第六章)
1
当PC电源打开后,CPU进入实模式,并从地址0XFFFF0执行,这个地址存放着ROM-BIOS。BIOS会执行某些系统检测,然后在物理地址0处开始初始化中断向量,此后,把启动设备第一扇区(就是磁盘引导扇区,512字节)的内容(bootsect)读入到0X7C00处,并跳转到这个地方。
bootsect程序把自己复制到内存0X90000处,并把setup程序读到内存0X90200处,其他部分(system)读到0X10000处,在这个期间系统显示"LOADING。。" 执行完后把控制权传递给setup
2
3
实验内容
修改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);
弄了很久,但是我还是没有完全完成实验,大部分完成但是输出有些不对,不知道怎么修改
实验楼 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