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

问题描述 投票:1回答:1

我有一个磁盘,每个磁道有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

这不起作用。

P.S。我认为每个磁道的扇区数为63的原因是,仅设置cl = 64也不起作用

assembly x86 bootloader osdev 16-bit
1个回答
1
投票

您先前的问题和评论旨在在硬盘驱动器上使用CHS(气缸,气缸盖,扇区)寻址。正如我之前提到的,硬盘驱动器最好使用Int 13h/AH=42H来避免完全使用CHS,而改用LBA(逻辑块地址)。逻辑块地址从0开始,一直到驱动器上的总扇区数减去1。处理LBA更加容易。

使用依赖CHS的BIOS功能的缺点是扇区固定为512字节。使用LBA assist BIOS translation(受BOCHS和QEMU支持),您可以从驱动器读取的最大扇区数为1024 * 255 * 63 = 16450560扇区或16450560 * 512 =‭8422686720‬(〜7.844GiB /〜8.423GB)。通过CHS寻址,您将无法阅读更多内容。

您可以使用我先前在related answer中描述的公式转换LBA:

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 13h/AH=8h可用于在引导加载程序运行时从BIOS检索这些值。在related answer中,我提供了示例代码,该示例代码使用Int 13h/AH=8h获取SPT和Heads并从32位LBA计算CHS,然后使用这些值通过Int 13h/AH=2h

读取扇区。

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 char h;  /* Head */
    unsigned char c;  /* Cylinder */
    unsigned char s;  /* Sector */

    unsigned int lba;

    if (argc != 4) {
        fprintf (stderr, "Usage: HEADS SPT LBA\n");
        return 1;
    }

    heads = atoi(argv[1]);
    spt = atoi(argv[2]);
    lba = atoi(argv[3]);

    /* Proper calculation */
    c = (lba / spt) / heads;
    h = (lba / spt) % heads;
    s = (lba % spt) + 1;

    printf ("LBA = %4d is CHS = (%2d, %2d, %2d)\n", lba, c, h, s);
    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

结果应该是:

LBA = 63是CHS =(0,1,28)

因此,您需要使用Cylinder = 0,Head = 1和Sector = 28设置对Int 13/AH=2h的调用,以读取驱动器上的第64个扇区(LBA = 63)。

© www.soinside.com 2019 - 2024. All rights reserved.