我们试图通过引导扇区代码中的各种数学指令来计算什么



在处理软盘的引导扇区时,我们会进行各种计算,比如

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_。代码将遵循以下结构:

  1. 计算LBADIVSPT。这将产生:商中的
    • (LBA ÷ SPT)
    • 余数中的(LBA mod SPT)
  2. 取步骤(1(中的余数并放入临时寄存器
  3. 将1添加到步骤(2(中的临时。该寄存器现在包含由S = (LBA mod SPT) + 1计算的扇区
  4. 取步骤(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#的位置

最新更新