DAY2-操作系统的引导(二)

6.4 bootsect.s读入setup.s

  1. 首先编写一个 setup.s,基本copy前面的bootsect.s代码,调整显示信息改成“Now we are in SETUP”。

  2. 编写 bootsect.s 中载入 setup.s 的关键代码load_setup和ok_load_setup部分,并去掉之前的无限循环代码。

6.5 再次编译

  1. 进入 linux-0.11 目录后
    1
    $ make BootImage
    此时会遇到ERROR,因为make根据Makefile指引执行了tools/build.c,而这里面会向我们要“system”的核心代码,所以我们先打个补丁。

6.6 修改 build.c

  1. build.c 从命令行参数得到 bootsect、setup 和 system 内核的文件名,将三者做简单的整理后一起写入 Image。
    所以我们注释掉 build.c 的尾部,忽略所有与system相关的工作。

  2. 再次编译运行

    1
    2
    3
    $ cd ~/oslab/linux-0.11
    $ make BootImage
    $ ../run

6.6实验结果

运行截图:
在这里插入图片描述

相关代码:
build.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

// 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);
}

setup.s

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
! /home/ly/oslab/linux-0.11/boot/setup.s
.globl begtext, begdata, begbss, endtext, enddata, endbss
.text
begtext:
.data
begdata:
.bss
begbss:
.text
entry _start ! 告知链接程序,从start标号开始执行
_start:
! 首先读入光标位置
mov ah,#0x03
xor bh,bh
int 0x10

! 显示字符串“Now we are in SETUP”
mov cx,#25
mov bx,#0x0007
mov bp,#msg2
mov ax,cs
mov es,ax
! es:bp 是显示字符串的地址
mov ax,#0x1301 ! write string, move cursor
int 0x10

inf_loop:
jmp inf_loop

msg2:
.byte 13,10
.ascii "Now we are in SETUP"
.byte 13,10,13,10

.org 510
boot_flag:
.word 0xAA55

.text
endtext:
.data
enddata:
.bss
endbss:

bootsect.s

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
! /home/ly/oslab/linux-0.11/boot/bootsect.s
.globl begtext, begdata, begbss, endtext, enddata, endbss
.text
begtext:
.data
begdata:
.bss
begbss:
.text

SETUPLEN = 2 ! setup程序的扇区(boot-sector)数
SETUPSEG = 0x07e0 ! 因为我们没有将bootsect移到0x9000

entry _start ! 告知链接程序,从start标号开始执行
_start:
! 首先读入光标位置
mov ah,#0x03
xor bh,bh
int 0x10
! 显示字符串 “Hello OS world, my name is LY”
mov cx,#35
mov bx,#0x0007
mov bp,#msg1

! es:bp 是显示字符串的地址
mov ax,#0x07c0 ! boot-sector的原始地址(段基址)
mov es,ax
mov ax,#0x1301 ! write string, move cursor
int 0x10

load_setup:
mov dx,#0x0000 ! 设置驱动器和磁头
mov cx,#0x0002 ! 设置扇区号和磁道
mov bx,#0x0200 ! 设置读入的内存地址:偏移512字节
mov ax,#0x0200+SETUPLEN
int 0x13 ! 读入2个setup.s扇区
jnc ok_load_setup ! 读入成功跳转
mov dx,#0x0000
mov ax,#0x0000
int 0x13
jmp load_setup ! 重复循环,再次尝试读取

ok_load_setup:
jmpi 0,SETUPSEG ! 跳到setup执行

msg1:
.byte 13,10
.ascii "Hello OS world, my name is LY"
.byte 13,10,13,10

.org 510
boot_flag:
.word 0xAA55

.text
endtext:
.data
enddata:
.bss
endbss:

6.7 setup.s 获取基本硬件参数

  1. 将硬件参数取出来放在内存 0x90000

6.8 显示获得的参数

  1. 显示 16 进制数

setup.s代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
! /home/ly/oslab/linux-0.11/boot/setup.s
.globl begtext, begdata, begbss, endtext, enddata, endbss
.text
begtext:
.data
begdata:
.bss
begbss:
.text

INITSEG = 0x9000 ! 原来bootsect所处到段
entry _start ! 告知链接程序,从start标号开始执行
_start:
! 首先读入光标位置
mov ah,#0x03
xor bh,bh
int 0x10
! 显示字符串“Now we are in SETUP”
mov cx,#25
mov bx,#0x0007
mov bp,#msg2
mov ax,cs
mov es,ax
! es:bp 是显示字符串的地址
mov ax,#0x1301 ! write string, move cursor
int 0x10

mov ax,cs
mov es,ax

! 获得参数。设置ds=0x9000,重置一下
! 读入光标位置
mov ax,#INITSEG
mov ds,ax
mov ah,#0x03
xor bh,bh
! 调用 0x10 中断
int 0x10
! 获取光标位置 => 0x9000:0
mov [0],dx

! 获取拓展内存大小 => 0x9000:2
mov ah,#0x88
int 0x15
mov [2],ax ! 将扩展内存存到0x90002处(1个字)

! 从 0x41 处拷贝 16 个字节(磁盘参数表)
! 获取硬盘参数 => 0x9000:80 大小:16B
mov ax,#0x0000
mov ds,ax
lds si,[4*0x41]
mov ax,#INITSEG
mov es,ax
mov di,#0x0004
mov cx,#0x10
! 重复16次
rep
movsb

! 准备打印
mov ax,cs
mov es,ax
mov ax,#INITSEG
mov ds,ax

! 打印
! Cursor Position
mov ah,#0x03
xor bh,bh
int 0x10
mov cx,#18
mov bx,#0x0007
mov bp,#msg_cursor
mov ax,#0x1301
int 0x10
mov dx,[0]
call print_hex
! Memory Size
mov ah,#0x03
xor bh,bh
int 0x10
mov cx,#14
mov bx,#0x0007
mov bp,#msg_memory
mov ax,#0x1301
int 0x10
mov dx,[2]
call print_hex
! Add KB
mov ah,#0x03
xor bh,bh
int 0x10
mov cx,#2
mov bx,#0x0007
mov bp,#msg_kb
mov ax,#0x1301
int 0x10
! Cyles
mov ah,#0x03
xor bh,bh
int 0x10
mov cx,#7
mov bx,#0x0007
mov bp,#msg_cyles
mov ax,#0x1301
int 0x10
mov dx,[4]
call print_hex
! Heads
mov ah,#0x03
xor bh,bh
int 0x10
mov cx,#8
mov bx,#0x0007
mov bp,#msg_heads
mov ax,#0x1301
int 0x10
mov dx,[6]
call print_hex
! Sectors
mov ah,#0x03
xor bh,bh
int 0x10
mov cx,#10
mov bx,#0x0007
mov bp,#msg_sectors
mov ax,#0x1301
int 0x10
mov dx,[12]
call print_hex

inf_loop:
jmp inf_loop

! 以16进制方式打印栈顶的16位数
print_hex:
mov cx,#4 ! 4个十六进制数字
print_digit:
rol dx,#4
mov ax,#0xe0f
and al,dl
add al,#0x30
cmp al,#0x3a
jl outp ! 是一个不大于十的数字
add al,#0x07 ! 是a~f,要多加7
outp:
int 0x10
loop print_digit
ret

! 打印回车换行
print_nl:
mov ax,#0xe0d ! CR
int 0x10
mov al,#0xa ! LF
int 0x10
ret

msg2:
.byte 13,10
.ascii "Now we are in SETUP"
.byte 13,10,13,10
msg_cursor:
.byte 13,10
.ascii "Cursor position:"
msg_memory:
.byte 13,10
.ascii "Memory Size:"
msg_cyles:
.byte 13,10
.ascii "Cyls:"
msg_heads:
.byte 13,10
.ascii "Heads:"
msg_sectors:
.byte 13,10
.ascii "Sectors:"
msg_kb:
.ascii "KB"

.org 510
boot_flag:
.word 0xAA55

.text
endtext:
.data
enddata:
.bss
endbss:

运行结果:
在这里插入图片描述