该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
146 !
! 该子程序将系统模块加载到内存地址0x10000 处,并确定没有跨越64KB 的内存边界。我们试图尽快
! 地进行加载,只要可能,就每次加载整条磁道的数据。
! 输入:es – 开始内存地址段值(通常是0x1000)
147 sread: .word 1+SETUPLEN ! sectors read of current track
! 当前磁道中已读的扇区数。开始时已经读进1 扇区的引导扇区
! bootsect 和setup 程序所占的扇区数SETUPLEN。
148 head: .word 0 ! current head !当前磁头号。
149 track: .word 0 ! current track !当前磁道号。
150
151 read_it:
! 测试输入的段值。从盘上读入的数据必须存放在位于内存地址64KB 的边界开始处,否则进入死循环。
! 清bx 寄存器,用于表示当前段内存放数据的开始位置。
152 mov ax,es
153 test ax,#0x0fff
154 die: jne die ! es must be at 64kB boundary ! es 值必须位于64KB 地址边界!
155 xor bx,bx ! bx is starting address within segment ! bx 为段内偏移位置。
156 rp_read:
! 判断是否已经读入全部数据。比较当前所读段是否就是系统数据末端所处的段(#ENDSEG),如果不是就
! 跳转至下面ok1_read 标号处继续读数据。否则退出子程序返回。
157 mov ax,es
158 cmp ax,#ENDSEG ! have we loaded all yet? ! 是否已经加载了全部数据?
159 jb ok1_read
160 ret
161 ok1_read:
! 计算和验证当前磁道需要读取的扇区数,放在ax 寄存器中。
! 根据当前磁道还未读取的扇区数以及段内数据字节开始偏移位置,计算如果全部读取这些未读扇区,
所
! 读总字节数是否会超过64KB 段长度的限制。若会超过,则根据此次最多能读入的字节数(64KB – 段
内
! 偏移位置),反算出此次需要读取的扇区数。
162 seg cs
163 mov ax,sectors ! 取每磁道扇区数。
164 sub ax,sread ! 减去当前磁道已读扇区数。
165 mov cx,ax ! cx = ax = 当前磁道未读扇区数。
166 shl cx,#9 ! cx = cx * 512 字节。
167 add cx,bx ! cx = cx + 段内当前偏移值(bx)
! = 此次读操作后,段内共读入的字节数。
168 jnc ok2_read ! 若没有超过64KB 字节,则跳转至ok2_read 处执行。
169 je ok2_read
170 xor ax,ax ! 若加上此次将读磁道上所有未读扇区时会超过64KB,则计算
171 sub ax,bx ! 此时最多能读入的字节数(64KB – 段内读偏移位置),再转换
172 shr ax,#9 ! 成需要读取的扇区数。
173 ok2_read:
174 call read_track
175 mov cx,ax ! cx = 该次操作已读取的扇区数。
176 add ax,sread ! 当前磁道上已经读取的扇区数。
177 seg cs
178 cmp ax,sectors ! 如果当前磁道上的还有扇区未读,则跳转到ok3_read 处。
179 jne ok3_read
! 读该磁道的下一磁头面(1 号磁头)上的数据。如果已经完成,则去读下一磁道。
180 mov ax,#1
181 sub ax,head ! 判断当前磁头号。
182 jne ok4_read ! 如果是0 磁头,则再去读1 磁头面上的扇区数据。
183 inc track ! 否则去读下一磁道。
184 ok4_read:
185 mov head,ax ! 保存当前磁头号。
186 xor ax,ax ! 清当前磁道已读扇区数。
187 ok3_read:
188 mov sread,ax ! 保存当前磁道已读扇区数。
189 shl cx,#9 ! 上次已读扇区数*512 字节。
190 add bx,cx ! 调整当前段内数据开始位置。
191 jnc rp_read ! 若小于64KB 边界值,则跳转到rp_read(156 行)处,继续读数据。
! 否则调整当前段,为读下一段数据作准备。
192 mov ax,es
193 add ax,#0x1000 ! 将段基址调整为指向下一个64KB 内存开始处。
194 mov es,ax
195 xor bx,bx ! 清段内数据开始偏移值。
196 jmp rp_read ! 跳转至rp_read(156 行)处,继续读数据。
197
! 读当前磁道上指定开始扇区和需读扇区数的数据到es:bx 开始处。参见第67 行下对BIOS 磁盘读中断
! int 0x13,ah=2 的说明。
! al – 需读扇区数;es:bx – 缓冲区开始位置。
198 read_track:
199 push ax
200 push bx
201 push cx
202 push dx
203 mov dx,track ! 取当前磁道号。
204 mov cx,sread ! 取当前磁道上已读扇区数。
205 inc cx ! cl = 开始读扇区。
206 mov ch,dl ! ch = 当前磁道号。
207 mov dx,head ! 取当前磁头号。
208 mov dh,dl ! dh = 磁头号。
209 mov dl,#0 ! dl = 驱动器号(为0 表示当前A 驱动器)。
210 and dx,#0x0100 ! 磁头号不大于1。
211 mov ah,#2 ! ah = 2,读磁盘扇区功能号。
212 int 0x13
213 jc bad_rt ! 若出错,则跳转至bad_rt。
214 pop dx
215 pop cx
216 pop bx
217 pop ax
218 ret
! 执行驱动器复位操作(磁盘中断功能号0),再跳转到read_track 处重试。
219 bad_rt: mov ax,#0
220 mov dx,#0
221 int 0x13
222 pop dx
223 pop cx
224 pop bx
225 pop ax
226 jmp read_track
227
228 /*
229 * This procedure turns off the floppy drive motor, so
230 * that we enter the kernel in a known state, and
231 * don't have to worry about it later.
232 */
! 这个子程序用于关闭软驱的马达,这样我们进入内核后它处于已知状态,以后也就无须担心它了。
233 kill_motor:
234 push dx
235 mov dx,#0x3f2 ! 软驱控制卡的驱动端口,只写。
236 mov al,#0 ! A 驱动器,关闭FDC,禁止DMA 和中断请求,关闭马达。
237 outb ! 将al 中的内容输出到dx 指定的端口去。
238 pop dx
239 ret
240
241 sectors:
242 .word 0 ! 存放当前启动软盘每磁道的扇区数。
243
244 msg1:
245 .byte 13,10 ! 回车、换行的ASCII 码。
246 .ascii "Loading system ..."
247 .byte 13,10,13,10 ! 共24 个ASCII 码字符。
248
249 .org 508 ! 表示下面语句从地址508(0x1FC)开始,所以root_dev
! 在启动扇区的第508 开始的2 个字节中。
250 root_dev:
251 .word ROOT_DEV ! 这里存放根文件系统所在的设备号(init/main.c 中会
用)。
252 boot_flag:
253 .word 0xAA55 ! 硬盘有效标识。
254
255 .text
256 endtext:
3.4 setup.s 程序
257 .data
258 enddata:
259 .bss
260 endbss: