TL;DR:驱动器(或模拟器或虚拟机中的驱动器映像)的大小可能会影响 BIOS 报告的磁头数、柱面数和每磁道扇区数 (SPT)。通过查询 BIOS 可能获得的值可能会有所不同,具体取决于大小,并且可能会因计算机和计算机的不同而有所不同。CHS翻译方案 http://www.uruk.org/orig-grub/PC_partitioning.txt被 BIOS 使用。
如果您的 BIOS 报告驱动器有 16 个磁头和 63 个 SPT,则 CHS(0, 1, 1) 应该是驱动器上的第 64 个扇区。然而,如果 BIOS 报告 16 个磁头和 36 个 SPT,则第 64 个扇区是 CHS(0, 1, 28)。如果使用具有 CHS 寻址的硬盘驱动器,请在引导加载程序运行时始终查询 BIOS 磁头数和 SPT 并计算逻辑块地址 (LBA)。强烈建议不要将柱面数、磁头数和 SPT 值硬编码到引导加载程序中。
不要使用 0x80 作为驱动器号,而是使用中的值DLBIOS 传递给您的引导加载程序。使用该值而不是对引导驱动器号进行硬编码。我有一些一般引导加载程序提示 https://stackoverflow.com/a/32705076/3857942这涵盖了您在进行遗留引导加载程序开发时可能希望考虑的事项以及其他事项。
柱面、磁头、扇区 (CHS) 寻址源自使用圆形盘片(或软盘)上的磁性介质的介质。维基百科有一个很好的article https://en.wikipedia.org/wiki/Cylinder-head-sector关于 CHS 的主题。从物理意义上描述 CHS 的图表:
图片来源维基百科 https://en.wikipedia.org/wiki/Cylinder-head-sector#/media/File:Hard_drive_geometry_-_English_-_2019-05-30.svg
磁道是一个同心圆(位于盘片的一侧),分为称为扇区的部分。驱动头读取盘片一侧的磁道。需要 2 个磁头才能访问物理盘片的两侧。圆柱体是介质上所有轨道的集合,它们一个叠一个地出现。
随着时间的推移,柱面、扇区和磁头的概念不再与物理实现相匹配,但 CHS 寻址仍用于访问设备上的数据以实现兼容性。逻辑块寻址 https://en.wikipedia.org/wiki/Logical_block_addressing(LBA) 最终取代了 CHS,并且是在 BIOS 中显示为硬盘驱动器的介质上的首选方法。 CHS 寻址仍然用在将自己呈现为 BIOS 软盘介质的设备上。并非所有 BIOS 都支持对软盘介质的 LBA 访问,在这种情况下,CHS 寻址仍然是首选机制。
您之前的问题和评论旨在在硬盘驱动器上使用 CHS 寻址。正如我之前提到的,最好与硬盘一起使用INT 13小时/AH=42H http://www.ctyme.com/intr/rb-0708.htm完全避免使用 CHS 并使用 LBA 代替。逻辑块地址从 0 开始,一直到驱动器上的总扇区数减 1。处理 LBA 要容易得多。
使用依赖 CHS 的 BIOS 功能的缺点是扇区固定为 512 字节。和LBA协助BIOS翻译 https://en.wikipedia.org/wiki/Logical_block_addressing#LBA-assisted_translation(BOCHS 和 QEMU 支持)您可以从驱动器读取的最大扇区数为 1024*255*63=16450560 扇区或 16450560*512=8422686720 (~7.844GiB/~8.423GB)。通过 CHS 寻址,您将无法读取超出范围的内容。
您可以使用我之前在中描述的公式来转换 LBA相关答案 https://stackoverflow.com/a/45495410/3857942:
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)
LBA addresses can be mapped to CHS tuples with the following formula
("mod" is the modulo operation, i.e. the remainder, and "÷" is
integer division, i.e. the quotient of the division where any
fractional part is discarded):
C = (LBA ÷ SPT) ÷ HPC
H = (LBA ÷ SPT) mod HPC
S = (LBA mod SPT) + 1
where C, H and S are the cylinder number, the head number, and the sector number
您可以使用以下方法进行反向计算(CHS 到 LBA):
CHS tuples can be mapped to LBA address with the following formula:
LBA = (C × HPC + H) × SPT + (S - 1)
为了计算磁盘上给定 LBA 的 CHS,您需要知道每磁道扇区数 (SPT) 和磁头数量。INT 13小时/AH=8小时 http://www.ctyme.com/intr/rb-0621.htm可用于在引导加载程序运行时从 BIOS 检索这些值。在一个相关答案 https://stackoverflow.com/a/47127909/3857942我提供了使用的示例代码INT 13小时/AH=8小时 http://www.ctyme.com/intr/rb-0621.htm获取 SPT 和 Heads 并从 32 位 LBA 计算 CHS,然后使用这些值读取扇区INT 13小时/AH=2小时 http://www.ctyme.com/intr/rb-0607.htm
LBA 到 CHS 转换器
下列C程序需要 3 个参数。 HEADS、SPT 和 LBA 使用上面的公式计算 CHS:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
unsigned int heads;
unsigned int spt; /* sectors per track */
unsigned int h; /* Head */
unsigned int c; /* Cylinder */
unsigned int s; /* Sector */
unsigned int lba;
if (argc != 4) {
fprintf (stderr, "Usage: HEADS SPT LBA\n");
return 1;
}
heads = atoi(argv[1]);
if (heads > 255 || heads < 1) {
fprintf (stderr, "Error: HEADS must be <= 255 and >= 1\n");
return 1;
}
spt = atoi(argv[2]);
if (spt > 63 || spt < 1) {
fprintf (stderr, "Error: SPT must be <= 63 and >= 1\n");
return 1;
}
lba = atoi(argv[3]);
/* Proper calculation */
c = (lba / spt) / heads;
h = (lba / spt) % heads;
s = (lba % spt) + 1;
printf ("SPT = %u, Heads = %u\n", spt, heads);
printf ("LBA = %u is CHS = (%u, %u, %u)\n\n", lba, c, h, s);
if (c >= 1024)
printf ("Can't use CHS because %u cylinders >= 1024, use LBA!\n", c);
else
printf ("DH = 0x%02X, CH = 0x%02X, CL = 0x%02X\n",
h, c & 0xff, s | ((c >> 2) & 0xc0));
return 0;
}
如果您想从 LBA 计算 CHS,此程序会很方便。在您的情况下,您想知道磁盘上第 64 个扇区的 CHS 值。 LBA 是从 0 开始的,因此 LBA 64-1=63。在您的评论/聊天中,BIOS 报告 SPT=36 和 Heads=16。如果您使用以下命令编译并运行上面的程序:
gcc lbatochs.c -o lbatochs
./lbatochs 16 36 63
结果应该是:
SPT = 36, Heads = 16
LBA = 63 is CHS = (0, 1, 28)
DH = 0x01, CH = 0x00, CL = 0x1C
对于 BIOS 报告为 SPT 63 和 16 磁头的驱动器,LBA 63 的结果应如下所示:
./lbatochs 16 63 63
SPT = 63, Heads = 16
LBA = 63 is CHS = (0, 1, 1)
DH = 0x01, CH = 0x00, CL = 0x01