在处理软盘的引导扇区时,我们会进行各种计算,比如
XOR DX,DX
DIVW 0x7C18
INC DL
MOV 0x7C3B, DL
XOR DX, DX
DIVW 0x7C1A
MOV 0x7C2A,DL
MOV 7C39,AX
RET
这只是一个代码示例,很明显,当我们浏览代码时,会有更多的计算,我们会发现各种DIV和MUL指令,我的问题是我们试图计算什么,以及如何计算,感谢
这段特定的代码将LBA地址转换为CHS地址。
LBA地址(或线性块地址(是指磁盘上的每个扇区都有一个从0到最大的数字(例如,对于总共有2880个扇区的1.44KB软盘,从0到2879(。CHS地址("Cylinder,Head,Sector"(更接近软盘的机械工作方式(并且被旧的BIOS磁盘功能使用(,但对于更高级别的软件来说不太方便。
计算结果为:
sector = LBA % sectors_per_cylinder + 1
head = (LBA / sectors_per_cylinder) % total_heads
cylinder = (LBA / sectors_per_cylinder) / total_heads
通过消除常见的子表达式,这变成:
sector = LBA % sectors_per_cylinder + 1
temp = LBA / sectors_per_cylinder;
head = temp % total_heads
cylinder = temp / total_heads
我们试图通过引导扇区代码中的各种数学指令来计算什么?
对于其他计算,这是不可能猜测的——我预计磁盘IO还会有几块(例如,根据文件的字节大小计算需要多少扇区(;也许是内存管理的一些计算(将东西与页面边界对齐,将真实模式的"segment:offset"转换为32位物理地址(;也许是一些用来记录时间的。。。
代码转换寄存器AX
中传递的逻辑块地址(LBA(,并将其转换为Cylinder/Head/Sector(CHS(。我在Translation of LBA to CHS
一节中回答一个相关的Stackoverflow问题时解释了一般计算。
LBA到CHS的翻译
定义:
LBA is the logical block address HPC is the maximum number of heads per cylinder (reported by disk drive, typically 16 for 28-bit LBA) SPT is the maximum number of sectors per track (reported by disk drive, typically 63 for 28-bit LBA) MOD is the modulo operation, i.e. the remainder ÷ is integer division, i.e. the quotient of the division where any fractional part is discarded
您需要的是一个正确的LBA到CHS转换例程。自从你对于FAT12导航的不同方面,将需要这样的功能文件结构最好创建一个函数。我们称之为
lba_to_chs
。在我们编写这样的代码之前,我们应该重新审视前面的等式:
C = LBA ÷ (HPC × SPT) H = (LBA ÷ SPT) mod HPC S = (LBA mod SPT) + 1
我们可以按原样实现,但如果我们重新计算圆柱体,我们可以减少我们必须做的工作量。
C = LBA ÷ (HPC × SPT)
可以重写为:C = LBA ÷ (HPC × SPT) C = LBA ÷ (SPT × HPC) C = (LBA ÷ SPT) × (1 ÷ HPC) C = (LBA ÷ SPT) ÷ HPC
如果我们现在看看我们的修正公式:
C = (LBA ÷ SPT) ÷ HPC H = (LBA ÷ SPT) mod HPC S = (LBA mod SPT) + 1
现在我们应该注意到
(LBA ÷ SPT)
在两个地方是重复的。我们只需要做一次方程式。由于x86DIV指令同时计算余数和商当我们做CCD_ 7时,也最终免费计算CCD_。代码将遵循以下结构:
- 计算LBADIVSPT。这将产生:商中的
(LBA ÷ SPT)
- 余数中的
(LBA mod SPT)
- 取步骤(1(中的余数并放入临时寄存器
- 将1添加到步骤(2(中的临时。该寄存器现在包含由
S = (LBA mod SPT) + 1
计算的扇区- 取步骤(1(中的商,除以HPC。
- 气缸数将是商
- 剩下的就是人头
我们已经将等式简化为几个DIV指令增量/加法。我们可以把事情简化得更多。如果我们假设我们是使用众所周知的IBM兼容磁盘格式,那么我们也可以说每个轨道的扇区(SPT(、磁头(HPC(、气缸、磁头和扇区总是小于256。当任何已知软盘上的最大LBA磁盘格式除以SPT,结果总是小于256。知道了这一点,我们就可以避免对圆柱体,并将它们放置在CL的顶部两个位中。我们还可以使用执行16位乘8位无符号除法的DIV指令。
您的汇编代码本质上非常相似。
功能输入:
- 函数的参数LBA在
AX
中 - 地址0x7C18处的字是存储在磁盘的BIOS参数块(BPB(中的每个磁道的扇区
- 地址0x7C1A处的字是存储在BPB中的磁头数
函数输出(计算后(:
- 地址0x7C3B处的字节是存储计算出的Sector#的位置
- 地址0x7C2A处的字节是存储计算出的磁头#的位置
- 地址0x7C39处的字是存储计算出的Cylinder#的位置