系统启动时,要查找IO.SYS、NTLDR、GRLDR等,若系统不支持扩展读,需获取磁盘磁头数及每磁道扇区数。常用方法有四种。
1. 使用int13/ah=08获取。
CL(位7-6)+CH(位7-0)=柱面数,DH=磁头数,CL(位5-0)=每磁道扇区数。
注意:柱面数、磁头数从0开始,扇区数从1开始。
对于BIOS识别为软盘的u盘或img磁盘映像,BL=10,但有的BIOS存在bug,会给出错误参数。
由于柱面数最大为3FF,磁盘字节总数最大为8Gb,超过则不能表示。
2. 使用int13/ah=48获取。
DS:SI的偏移04=柱面数,偏移08=磁头数,偏移0C=每磁道扇区数,偏移10=磁盘总扇区数。
注意:柱面数、磁头数、扇区数从1开始。
应测试偏移02的标记(位7-0),若位1等于0,则不支持c/h/s参数获取,给出的c/h/s参数可能不正确,但磁盘总扇区数还是正确的。
3. 使用引导扇区DBR的BPB参数表获取。
对于FAT12,偏移1A=磁头数,偏移18=每磁道扇区数,偏移13=该分区总扇区数。
对于FAT16,偏移1A=磁头数,偏移18=每磁道扇区数,偏移20=该分区总扇区数。
对于FAT32、EXT2、EXT3,偏移1A=磁头数,偏移18=每磁道扇区数,偏移20=该分区总扇区数。
对于NTFS,偏移1A=磁头数,偏移18=每磁道扇区数,偏移28=该分区总扇区数。
注意:柱面数、磁头数、扇区数从1开始。
4. 使用主引导记录MBR获取。
偏移1C3=磁头数,偏移1C4(位5-0)=每磁道扇区数,偏移1CA=分区总扇区数。
注意:磁头数从0开始,扇区数从1开始。
本人认为第3、4种方法最方便可靠。因为查找IO.SYS、NTLDR、GRLDR等时,除了获取h/s参数,还需要获取BPB参数表的其他参数,如每簇扇区数、保留扇区数、隐含扇区数、$MFT(主文件表)的逻辑簇号、节点大小等等。既然要用到MBR及BPB,何不一并获取,而要舍近求远,舍简求繁?或许有人曰h/s参数可能被病毒破坏,那MBR及BPB的其他参数不也会被破坏?
5 对于c/h/s参数的探测,grldrstart.S采用逐次测试法,探测磁头数从1探测到FF,最少1次,最多255次,平均128次。若采用对折逼近法,只需8或9次。
程序代码如下:
testing: pusha
push ds
push es
mov bx,5000h
mov es,bx
mov ds,bx
xor bp,bp
;初始化测试扇区参数
mov cx,20h ;初始测试值
mov bh,40h ;测试上限+1
xor bl,bl ;测试下限
read: pusha
xor bx,bx ;读到5000:0000
cmp bp,0 ;测试扇区数?
jne read_head ;不是
;测试每磁道扇区数
mov ax,0201h
xor ch,ch
xor dh,dh
int 13h
jmp read_end ;成功
read_head: ;测试最大磁头号
mov dh,cl
mov ax,0201h
mov cx,1
int 13h
read_end: popa
jb failure
;测试成功处理
mov ch,cl ;保存成功值
mov bl,cl ;修正下限
mov cl,bh
;计算新测试值
new: sub cl,bl
shr cl,1
add cl,bl
cmp cl,0
je err
cmp ch,cl ;测试完毕退出
je done
jmp read
;测试失败处理
failure: mov bh,cl ;修正上限
jmp new
done: test bp,1 ;测试完最大磁头号?
je done_sector ;不是
inc ch
mov cs:,ch ;保存测试成功的磁头数
jmp test_end
done_sector:
mov cs:,ch ;保存测试成功的每磁头扇区数
;测试最大磁头号
or bp,1 ;测试最大磁头号标记
;专为虚拟机vpc的bug设置
;读1扇区 0-0-1 -> 5000:0000
xor bx,bx
mov ax,0201h
mov cx,1
xor dh,dh
int 13h
;读1扇区 0-2-1 -> 5000:0200
mov ax,0201h
mov dh,2
mov bx,0200h
int 13h
;比较 5000:0000<>5000:0200
xor si,si
mov di,0200h
mov cx,80h
repz cmpsd
jne general ;不相等正常测试
mov byte ptr cs:,2
jmp test_end
general: ;正常测试最大磁头号
;初始化测试磁头参数
mov cx,7fh ;初始测试值
mov bh,0ffh ;测试上限+1
xor bl,bl ;测试下限
jmp read
err: stc
test_end:
pop es
pop ds
popa
ret
上传一个探测程序,请把rar改为com。
When the system starts, it needs to look for IO.SYS, NTLDR, GRLDR, etc. If the system doesn't support extended reading, it needs to obtain the number of disk heads and the number of sectors per track. There are four common methods.
1. Obtained using int13/ah=08.
CL (bits 7-6) + CH (bits 7-0) = number of cylinders, DH = number of heads, CL (bits 5-0) = number of sectors per track.
Note: The number of cylinders and heads start from 0, and the number of sectors starts from 1.
For a USB flash drive or img disk image recognized as a floppy disk by the BIOS, BL=10, but some BIOS have bugs and give incorrect parameters.
Since the maximum number of cylinders is 3FF, the maximum total number of bytes of the disk is 8Gb, and it cannot be represented if exceeded.
2. Obtained using int13/ah=48.
Offset 04 of DS:SI = number of cylinders, offset 08 = number of heads, offset 0C = number of sectors per track, offset 10 = total number of sectors of the disk.
Note: The number of cylinders, heads, and sectors start from 1.
The flag at offset 02 (bits 7-0) should be tested. If bit 1 is 0, the acquisition of c/h/s parameters is not supported, and the given c/h/s parameters may be incorrect, but the total number of sectors of the disk is still correct.
3. Obtained using the BPB parameter table of the boot sector DBR.
For FAT12, offset 1A = number of heads, offset 18 = number of sectors per track, offset 13 = total number of sectors of this partition.
For FAT16, offset 1A = number of heads, offset 18 = number of sectors per track, offset 20 = total number of sectors of this partition.
For FAT32, EXT2, EXT3, offset 1A = number of heads, offset 18 = number of sectors per track, offset 20 = total number of sectors of this partition.
For NTFS, offset 1A = number of heads, offset 18 = number of sectors per track, offset 28 = total number of sectors of this partition.
Note: The number of cylinders, heads, and sectors start from 1.
4. Obtained using the master boot record MBR.
Offset 1C3 = number of heads, offset 1C4 (bits 5-0) = number of sectors per track, offset 1CA = total number of sectors of the partition.
Note: The number of heads starts from 0, and the number of sectors starts from 1.
I think the 3rd and 4th methods are the most convenient and reliable. Because when looking for IO.SYS, NTLDR, GRLDR, etc., in addition to obtaining the h/s parameters, other parameters of the BPB parameter table need to be obtained, such as the number of sectors per cluster, the number of reserved sectors, the number of hidden sectors, the logical cluster number of $MFT (Master File Table), the node size, etc. Since MBR and BPB need to be used, why not obtain them together, instead of going the long way and making it more complicated? Maybe someone says that the h/s parameters may be damaged by viruses, but aren't the other parameters of MBR and BPB also likely to be damaged?
5. For the detection of c/h/s parameters, grldrstart.S uses a successive testing method, detecting the number of heads from 1 to FF, at least 1 time, at most 255 times, with an average of 128 times. If the bisection approximation method is used, only 8 or 9 times are needed.
The program code is as follows:
testing: pusha
push ds
push es
mov bx,5000h
mov es,bx
mov ds,bx
xor bp,bp
;Initialize test sector parameters
mov cx,20h ;Initial test value
mov bh,40h ;Test upper limit + 1
xor bl,bl ;Test lower limit
read: pusha
xor bx,bx ;Read to 5000:0000
cmp bp,0 ;Test sector number?
jne read_head ;No
;Test number of sectors per track
mov ax,0201h
xor ch,ch
xor dh,dh
int 13h
jmp read_end ;Success
read_head: ;Test maximum number of heads
mov dh,cl
mov ax,0201h
mov cx,1
int 13h
read_end: popa
jb failure
;Process successful test
mov ch,cl ;Save successful value
mov bl,cl ;Correct lower limit
mov cl,bh
;Calculate new test value
new: sub cl,bl
shr cl,1
add cl,bl
cmp cl,0
je err
cmp ch,cl ;Exit after testing
je done
jmp read
;Process failed test
failure: mov bh,cl ;Correct upper limit
jmp new
done: test bp,1 ;Finished testing maximum number of heads?
je done_sector ;No
inc ch
mov cs:,ch ;Save successfully tested number of heads
jmp test_end
done_sector:
mov cs:,ch ;Save successfully tested number of sectors per head
;Test maximum number of heads
or bp,1 ;Test maximum number of heads flag
;Set specifically for the bug of virtual machine vpc
;Read 1 sector 0-0-1 -> 5000:0000
xor bx,bx
mov ax,0201h
mov cx,1
xor dh,dh
int 13h
;Read 1 sector 0-2-1 -> 5000:0200
mov ax,0201h
mov dh,2
mov bx,0200h
int 13h
;Compare 5000:0000<>5000:0200
xor si,si
mov di,0200h
mov cx,80h
repz cmpsd
jne general ;Not equal, normal testing
mov byte ptr cs:,2
jmp test_end
general: ;Normal testing of maximum number of heads
;Initialize test head parameters
mov cx,7fh ;Initial test value
mov bh,0ffh ;Test upper limit + 1
xor bl,bl ;Test lower limit
jmp read
err: stc
test_end:
pop es
pop ds
popa
ret
Upload a detection program, please change rar to com.