使用BIOS int 13h访问不同磁头的扇区

2024-03-24

我的磁盘每磁道有 63 个扇区。 (根据我的观察,我假设) 我想使用 int 13h 读取 16 位引导加载程序上的扇区。 例如,如果我想读取扇区号 63,我将执行以下操作:

mov dl,0x80;Drive number
mov dh,0 ;This is head number/platter number
mov ch,0  ;This is cylinder number
mov cl,63 ;Sector number
mov ah,0x02 ;interrupt function
mov al,1  ;Number of sectors to be read
xor bx,bx 
mov es,bx ;Making es=0
mov bx,0x8000 ;Any random buffer address
int 0x13

上面的代码按预期工作。

现在我想读取扇区 64。我相信它将是柱面 0、磁头 1、扇区 1。 我用:

mov dl,0x80;Drive number
mov dh,1 ;This is head number/platter number
mov ch,0  ;This is cylinder number
mov cl,1 ;Sector number
mov ah,0x02 ;interrupt function
mov al,1  ;Number of sectors to be read
xor bx,bx 
mov es,bx ;Making es=0
mov bx,0x8000 ;Any random buffer address
int 0x13

这是行不通的。

附:我之所以认为每磁道的扇区数为 63 是因为简单地设置 cl = 64 也不起作用


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
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用BIOS int 13h访问不同磁头的扇区 的相关文章

  • 逆向工程的汇编语言[关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 为什么push指令会改变rsp的值? [复制]

    这个问题在这里已经有答案了 我正在检查 Ericksons Hacking The Art of Exploitation 中的这段代码片段 void test function int a int b int c int d int fl
  • 如何在汇编器中实现相对 JMP (x86)?

    在为 x86 平台构建汇编程序时 我遇到了一些编码问题JMP操作说明 OPCODE INSTRUCTION SIZE EB cb JMP rel8 2 E9 cw JMP rel16 4 because of 0x66 16 bit pre
  • 在MIPS中,有符号加法、无符号加法、有符号减法和无符号减法之间有什么区别?

    add rd rs rt addu rd rs rt sub rd rs rt subu rd rs rt 在MIPS中 有符号加法 无符号加法 有符号减法和无符号减法之间有什么区别 如果它们的结果相同 那么分类为使用有符号和无符号方法有什
  • 源操作数和目标操作数是否需要相同大小?

    我刚刚尝试了这个问题 要求你解释一下代码行有什么问题 movl eax rdx 解决方案表明目标操作数的大小错误 仅当从较大尺寸变为较小尺寸时才 非法 还是源操作数和目标操作数对于所有指令 或至少 mov 类类型 必须具有相同的尺寸 是的
  • 为什么允许 gcc 从结构推测加载?

    显示 gcc 优化和可能出现故障的用户代码的示例 下面代码片段中的函数 foo 将仅加载结构成员 A 或 B 之一 至少这是未优化代码的意图 typedef struct int A int B Pair int foo const Pai
  • printf 内部如何工作? [复制]

    这个问题在这里已经有答案了 可能的重复 无需汇编的 C C 函数定义 https stackoverflow com questions 2442966 c c function definitions without assembly 你
  • 如何正确确定Intel处理器的-march和-mtune?

    我目前正在从源代码构建一个对我来说性能至关重要的软件 因此 我想对其进行优化 以便在我的特定 Intel CPU 上运行 构建过程要求我设置 march 和 mtune 标志 如果在我的处理器节点上我使用 gcc march native
  • `__asm nop` 在 Windows 中相当于 GCC 编译器中的 `asm volatile("nop");`

    在 Windows 中 可以 asm nop被交换为asm volatile nop 在 GCC 编译器中使用 并产生相同的结果 我读过volatile 在 GCC 中 保证调用不会被优化掉 然而 它不能直接移植到 Windows 我很好奇
  • 我如何使其解密而不是加密?

    想知道如何从加密代码中获取此代码并使用相同的代码来创建解密 我知道这意味着我必须反转一些指令并重新排序 但我无法弄清楚哪些指令需要重新排序 哪些不需要 编辑 这是完整的函数 可以让事情变得更清晰一些 对堆栈溢出非常陌生 因此对于任何混淆表示
  • fstcw 汇编操作数类型不匹配

    我正在尝试使用 C 中的内联汇编中指定的舍入模式对输入双精度舍入进行舍入 为此 我需要使用以下命令获取 FPU 控制字fstcw然后更改字中的位 不幸的是我在第一行遇到了错误 double roundD double n RoundingM
  • 内联汇编中的内存偏移

    在 A64 汇编器中 有不同的方法来指定地址 base 0 Simple register exclusive Immediate Offset base imm Offset Immediate Offset base Xm LSL im
  • 不知道如何一次打印整个日历[关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 cseg segment assume cs cseg ds cseg org 100H begin mov es cs video mov
  • 比较击键 - 装配 CCS64

    I want to compare keystrokes in assembly CCS64 If I type in the same key in a row I want to do something example A A do
  • 为什么 godbolt 生成的 asm 输出与我在 Visual Studio 中的实际 asm 代码不同?

    这是生成的代码godbolt https godbolt org z 1F1t6Z 以下是 Visual Studio 在我的 main asm 文件上生成的相同代码 通过 汇编器输出 字段下的 项目 gt C C gt 输出文件 gt 使
  • NOP 雪橇如何工作?

    我找不到回答这个问题的好来源 我知道 nop sled 是一种用于规避缓冲区溢出攻击中堆栈随机化的技术 但我无法理解它是如何工作的 有什么简单的例子可以说明这种方法 128 字节 nop sled 等术语是什么意思 有些攻击包括使程序跳转到
  • 在 DLL 中,函数表的结构如何?

    我一直在研究不明确支持我的操作系统的设备库的实现 特别是 我有一个反汇编的 DLL 以及大量的支持源代码 现在 功能表 导出表是如何构造的 我的理解是 第一个结构 data部分是 RVA 表 接下来是通过索引链接到第一个地址表的字符串表 这
  • 如何查看JVM中JIT编译的代码?

    有什么方法可以查看 JVM 中 JIT 生成的本机代码吗 一般用法 正如其他答案所解释的 您可以使用以下 JVM 选项运行 XX UnlockDiagnosticVMOptions XX PrintAssembly 根据特定方法进行过滤 您
  • g++ 内联汇编括号中不匹配

    g 向我抱怨以下代码中缺少括号 1 2 3 v v v asm volatile inb 1 0 a result Nd portnumber 1 2 3 正如您所看到的 括号是匹配
  • 跨 AVX 通道的最佳方式是什么?

    有些问题具有类似的标题 但我的问题涉及其他地方未涵盖的一个非常具体的用例 我有 4 个 128d 寄存器 x0 x1 x2 x3 我想将它们的内容重新组合在 5 个 256d 寄存器 y0 y1 y2 y3 y4 中 以准备其他计算 on

随机推荐