⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 1120.html

📁 著名的linux英雄站点的文档打包
💻 HTML
📖 第 1 页 / 共 5 页
字号:
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!<br>
!!INT 13 - DISK - READ SECTOR(S) INTO MEMORY<br>
!! AH = 02h<br>
!! AL = number of sectors to read (must be nonzero)<br>
!! CH = low eight bits of cylinder number<br>
!! CL = sector number 1-63 (bits 0-5)<br>
!! high two bits of cylinder (bits 6-7, hard disk only)<br>
!! DH = head number<br>
!! DL = drive number (bit 7 set for hard disk)<br>
!! ES:BX -&gt; data buffer<br>
!! Return: CF set on error<br>
!! if AH = 11h (corrected ECC error), AL = burst length<br>
!! CF clear if successful<br>
!! AH = status (see #00234)<br>
!! AL = number of sectors transferred (only valid if CF set for some<br>
!! BIOSes)<br>
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!<br>
<br>
<br>
ok_load_setup:<br>
<br>
! 取得磁盘驱动器参数,特别是每磁道扇区数(nr of sectors/track);<br>
<br>
#if 0<br>
<br>
! bde - Phoenix BIOS手册中提到功能0x08只对硬盘起作用。<br>
! 但它对于我的一个BIOS(1987 Award)不起作用。<br>
! 不检查错误码是致命的错误。<br>
<br>
xor dl,dl<br>
mov ah,#0x08 ! AH=8用于取得驱动器参数;<br>
int 0x13<br>
xor ch,ch<br>
<br>
!!!!!!!!!!!!!!!!!!!!!!!!!!!<br>
!! INT 13 - DISK - GET DRIVE PARAMETERS (PC,XT286,CONV,PS,ESDI,SCSI)<br>
!! AH = 08h<br>
!! DL = drive (bit 7 set for hard disk)<br>
!!Return: CF set on error<br>
!! AH = status (07h) (see #00234)<br>
!! CF clear if successful<br>
!! AH = 00h<br>
!! AL = 00h on at least some BIOSes<br>
!! BL = drive type (AT/PS2 floppies only) (see #00242)<br>
!! CH = low eight bits of maximum cylinder number<br>
!! CL = maximum sector number (bits 5-0)<br>
!! high two bits of maximum cylinder number (bits 7-6)<br>
!! DH = maximum head number<br>
!! DL = number of drives<br>
!! ES:DI -&gt; drive parameter table (floppies only)<br>
!!!!!!!!!!!!!!!!!!!!!!!!!!!!<br>
<br>
#else<br>
<br>
! 好象没有BIOS调用可取得扇区数。如果扇区36可以读就推测是36个扇区,<br>
! 如果扇区18可读就推测是18个扇区,如果扇区15可读就推测是15个扇区,<br>
! 否则推测是9. [36, 18, 15, 9]<br>
<br>
mov si,#disksizes ! ds:si-&gt;要测试扇区数大小的表;<br>
<br>
probe_loop:<br>
lodsb !! ds:si所指的字节 =&gt;al, si=si+1;<br>
cbw ! 扩展为字(word);<br>
mov sectors, ax ! 第一个值是36,最后一个是9;<br>
cmp si,#disksizes+4<br>
jae got_sectors ! 如果所有测试都失败了,就试9;<br>
xchg ax,cx ! cx = 磁道和扇区(第一次是36=0x0024);<br>
xor dx,dx ! 驱动器0,磁头0;<br>
xor bl,bl !! 设置缓冲区es:bx = 0x9000:0x0a00(578.5k);<br>
mov bh,setup_sects !! setup_sects = 4 (共2k);<br>
inc bh<br>
shl bh,#1 ! setup后面的地址(es=cs);<br>
mov ax,#0x0201 ! 功能2(读),1个扇区;<br>
int 0x13<br>
jc probe_loop ! 如果不对,就试用下一个值;<br>
<br>
#endif<br>
<br>
got_sectors:<br>
<br>
! 恢复es<br>
<br>
mov ax,#INITSEG<br>
mov es,ax ! es = 0x9000;<br>
<br>
! 打印一些无用的信息(换行后,显示Loading)<br>
<br>
mov ah,#0x03 ! 读光标位置;<br>
xor bh,bh<br>
int 0x10<br>
<br>
mov cx,#9<br>
mov bx,#0x0007 ! 页0,属性7 (normal);<br>
mov bp,#msg1<br>
mov ax,#0x1301 ! 写字符串,移动光标;<br>
int 0x10<br>
<br>
! ok, 我们已经显示出了信息,现在<br>
! 我们要加载系统了(到0x10000处)(64k处)<br>
<br>
mov ax,#SYSSEG<br>
mov es,ax ! es=0x01000的段;<br>
call read_it !! 读system,es为输入参数;<br>
call kill_motor !! 关闭驱动器马达;<br>
call print_nl !! 打印回车换行;<br>
<br>
! 这以后,我们来检查要使用哪个根设备(root-device)。如果已指定了设备(!=0)<br>
! 则不做任何事而使用给定的设备。否则的话,使用/dev/fd0H2880 (2,32)或/dev/PS0<br>
(2,2icon_cool.gif<br>
! 或者是/dev/at0 (2,icon_cool.gif之一,这取决于我们假设我们知道的扇区数而定。<br>
!! |__ ps0?? (x,y)--表示主、次设备号?<br>
<br>
seg cs<br>
mov ax,root_dev<br>
or ax,ax<br>
jne root_defined<br>
seg cs<br>
mov bx,sectors !! sectors = 每磁道扇区数;<br>
mov ax,#0x0208 ! /dev/ps0 - 1.2Mb;<br>
cmp bx,#15<br>
je root_defined<br>
mov al,#0x1c ! /dev/PS0 - 1.44Mb !! 0x1C = 28;<br>
cmp bx,#18<br>
je root_defined<br>
mov al,0x20 ! /dev/fd0H2880 - 2.88Mb;<br>
cmp bx,#36<br>
je root_defined<br>
mov al,#0 ! /dev/fd0 - autodetect;<br>
root_defined:<br>
seg cs<br>
mov root_dev,ax !! 其中保存由设备的主、次设备号;<br>
<br>
! 这以后(所有程序都加载了),我们就跳转至<br>
! 被直接加载到boot块后面的setup程序去:<br>
<br>
jmpi 0,SETUPSEG !! 跳转到0x9020:0000(setup程序的开始位置);<br>
<br>
<br>
! 这段程序将系统(system)加载到0x10000(64k)处,<br>
! 注意不要跨越64kb边界。我们试图以最快的速度<br>
! 来加载,只要可能就整个磁道一起读入。<br>
!<br>
! 输入(in): es - 开始地址段(通常是0x1000)<br>
!<br>
sread: .word 0 ! 当前磁道已读的扇区数;<br>
head: .word 0 ! 当前磁头;<br>
track: .word 0 ! 当前磁道;<br>
<br>
read_it:<br>
mov al,setup_sects<br>
inc al<br>
mov sread,al !! 当前sread=5;<br>
mov ax,es !! es=0x1000;<br>
test ax,#0x0fff !! (ax AND 0x0fff, if ax=0x1000 then zero-flag=1 );<br>
die: jne die ! es 必须在64kB的边界;<br>
xor bx,bx ! bx 是段内的开始地址;<br>
rp_read:<br>
#ifdef __BIG_KERNEL__<br>
#define CALL_HIGHLOAD_KLUDGE .word 0x1eff, 0x220 ! 调用 far * bootsect_kludge<br>
! 注意: as86不能汇编这;<br>
CALL_HIGHLOAD_KLUDGE ! 这是在setup.S中的程序;<br>
#else<br>
mov ax,es<br>
sub ax,#SYSSEG ! 当前es段值减system加载时的启始段值(0x1000);<br>
#endif<br>
cmp ax,syssize ! 我们是否已经都加载了?(ax=0x7f00 ?);<br>
jbe ok1_read !! if ax &lt;= syssize then 继续读;<br>
ret !! 全都加载完了,返回!<br>
ok1_read:<br>
mov ax,sectors !! sectors=每磁道扇区数;<br>
sub ax,sread !! 减去当前磁道已读扇区数,al=当前磁道未读的扇区数(ah=0);<br>
mov cx,ax<br>
shl cx,#9 !! 乘512,cx = 当前磁道未读的字节数;<br>
add cx,bx !! 加上段内偏移值,es:bx为当前读入的数据缓冲区地址;<br>
jnc ok2_read !! 如果没有超过64K则继续读;<br>
je ok2_read !! 如果正好64K也继续读;<br>
xor ax,ax<br>
sub ax,bx<br>
shr ax,#9<br>
ok2_read:<br>
call read_track !! es:bx -&gt;缓冲区,al=要读的扇区数,也即当前磁道未读的扇区数;<br>
<br>
mov cx,ax !! ax仍为调用read_track之前的值,即为读入的扇区数;<br>
add ax,sread !! ax = 当前磁道已读的扇区数;<br>
cmp ax,sectors !! 已经读完当前磁道上的扇区了吗?<br>
jne ok3_read !! 没有,则跳转;<br>
mov ax,#1<br>
sub ax,head !! 当前是磁头1吗?<br>
jne ok4_read !! 不是(是磁头0)则跳转(此时ax=1);<br>
inc track !! 当前是磁头1,则读下一磁道(当前磁道加1);<br>
ok4_read:<br>
mov head,ax !! 保存当前磁头号;<br>
xor ax,ax !! 本磁道已读扇区数清零;<br>
ok3_read:<br>
mov sread,ax !! 存本磁道已读扇区数;<br>
shl cx,#9 !! 刚才一次读操作读入的扇区数 * 512;<br>
add bx,cx !! 调整数据缓冲区的起始指针;<br>
jnc rp_read !! 如果该指针没有超过64K的段内最大偏移量,则跳转继续读操作;<br>
mov ax,es !! 如果超过了,则将段地址加0x1000(下一个64K段);<br>
add ah,#0x10<br>
mov es,ax<br>
xor bx,bx !! 缓冲区地址段内偏移量置零;<br>
jmp rp_read !! 继续读操作;<br>
<br>
<br>
read_track:<br>
pusha !! 将寄存器ax,cx,dx,bx,sp,bp,si,di压入堆栈;<br>
pusha<br>
mov ax,#0xe2e ! loading... message 2e = . !! 显示一个.<br>
mov bx,#7<br>
int 0x10<br>
popa<br>
<br>
mov dx,track !! track = 当前磁道;<br>
mov cx,sread<br>
inc cx !! cl = 扇区号,要读的起始扇区;<br>
mov ch,dl !! ch = 磁道号的低8位;<br>
mov dx,head !!<br>
mov dh,dl !! dh = 当前磁头号;<br>
and dx,#0x0100 !! dl = 驱动器号(0);<br>
mov ah,#2 !! 功能2(读),es:bx指向读数据缓冲区;<br>
<br>
push dx ! 为出错转储保存寄存器的值到堆栈上;<br>
push cx<br>
push bx<br>
push ax<br>
<br>
int 0x13<br>
jc bad_rt !! 如果出错,则跳转;<br>
add sp, #8 !! 清(放弃)堆栈上刚推入的4个寄存器值;<br>
popa<br>
ret<br>
<br>
bad_rt: push ax ! 保存出错码;<br>
call print_all ! ah = error, al = read;<br>
<br>
<br>
xor ah,ah<br>
xor dl,dl<br>
int 0x13<br>
<br>
<br>
add sp,#10<br>
popa<br>
jmp read_track<br>
<br>
/*<br>
* print_all是用于调试的。<br>
* 它将打印出所有寄存器的值。所作的假设是<br>
* 从一个子程序中调用的,并有如下所示的堆栈帧结构<br>
* dx<br>
* cx<br>
* bx<br>
* ax<br>
* error<br>
* ret &lt;- sp<br>
*<br>
*/<br>
<br>
print_all:<br>
mov cx,#5 ! 出错码 + 4个寄存器<br>
mov bp,sp<br>
<br>
print_loop:<br>
push cx ! 保存剩余的计数值<br>
call print_nl ! 为了增强阅读性,打印换行<br>
<br>
cmp cl, #5<br>
jae no_reg ! 看看是否需要寄存器的名称<br>
<br>
mov ax,#0xe05 + A - l<br>
sub al,cl<br>
int 0x10<br>
<br>
mov al,#X<br>
int 0x10<br>
<br>
mov al,#:<br>
int 0x10<br>
<br>
no_reg:<br>
add bp,#2 ! 下一个寄存器<br>
call print_hex ! 打印值<br>
pop cx<br>
loop print_loop<br>
ret<br>
<br>
print_nl: !! 打印回车换行。<br>
mov ax,#0xe0d ! CR<br>
int 0x10<br>
mov al,#0xa ! LF<br>
int 0x10<br>
ret<br>
<br>
/*<br>
* print_hex是用于调试目的的,打印出<br>
* ss:bp所指向的十六进制数。<br>
* !! 例如,十六进制数是0x4321时,则al分别等于4,3,2,1调用中断打印出来 4321<br>
*/<br>
<br>
print_hex:<br>
mov cx, #4 ! 4个十六进制数字<br>
mov dx, (bp) ! 将(bp)所指的值放入dx中<br>
print_digit:<br>
rol dx, #4 ! 循环以使低4比特用上 !! 取dx的高4比特移到低4比特处。<br>
mov ax, #0xe0f ! ah = 请求的功能值,al = 半字节(4个比特)掩码。<br>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -