无法从C中的磁盘读取扇区 [英] Cannot read sectors from disk in C

查看:176
本文介绍了无法从C中的磁盘读取扇区的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 i686-elf-gcc 交叉编译器生成以实模式运行的代码。

I'm using an i686-elf-gcc cross compiler to generate code to run in real-mode.

I正在尝试从我的内核读取扇区。我知道这是我的内核所在的位置,在第二个扇区中,第0个驱动器,第0个磁道。它构建良好,但是在我调用read之后,扇区读仍为0。

I'm trying to read a sector from my kernel. I know this is the location where my kernel is located, in the second sector, 0th drive, 0th track. It builds fine, but after I call read, sectors_read is still 0.

u8 status;
u8 sectors_read;
read(1, 0, 1, 0, 0, status, sectors_read);
kprint("STATUS: ");
hex_to_ascii(status, num_str_buffer);
kprint(num_str_buffer);
kprint("\nSECTORS READ: ");
num_str_buffer[0] = '\0';
hex_to_ascii(sectors_read, num_str_buffer);
kprint(num_str_buffer);


void read(u8 sector_size, u8 track, u8 sector, u8 head, u8 drive, u8 status, u8 sectors_read)
{
    asm volatile("mov $2, %AH");
    asm volatile("mov %0, %%AL" : : "r"(sector_size) : );
    asm volatile("mov %0, %%CH" : : "r"(track) : );
    asm volatile("mov %0, %%CL" : : "r"(sector) : );
    asm volatile("mov %0, %%DH" : : "r"(head));
    asm volatile("mov %0, %%DL" : : "r"(drive));
    asm volatile("int $0x13");
    asm volatile("mov %%AH, %0":"=r"(status) : );
    asm volatile("mov %%AL, %0":"=r"(sectors_read) : );
}


推荐答案

有很多错误使用您的 read 函数。由于您尚未发布可复制的示例,甚至没有足够的详细信息来了解您要使用的工具链,因此,我无法为您的问题提供确切的答案。这是很多错误的地方:

There's a bunch of stuff wrong with your read function. As you have not posted a reproducible example or even enough details to know what toolchain you are programming for, I cannot give a definite answer to your problems. Here are a number of things that are wrong:


  • 在C语言中,所有函数参数均按值传递。在 read 中分配给 status sectors_read 的状态不会影响您在被调用方中传递的参数。

  • 您不会告诉编译器您破坏了 ax cx dx 还是这些寄存器的内容很重要。因此,编译器可能将它们用于任何其喜欢的目的,从而干扰您想要的语义。要解决此问题,请使用寄存器约束而不是 mov 指令将参数放入正确的寄存器中。

  • 您似乎没有设置 es:bx 到要读取数据的缓冲区的地址。因此,BIOS会将数据读取到 es:bx 指向的任何地址中,实质上是覆盖随机内存。

  • in C, all function arguments are passed by value. Assigning to status and sectors_read in read will not affect the arguments you pass in the callee. Pass a pointer instead.
  • you do not tell the compiler that you clobber ax, cx, and dx or that the contents of these registers are of importance. The compiler might thus use them for whatever purpose it likes, interfering with the semantics you intend. To fix this, use register constraints instead of mov instructions to place the arguments into the right registers.
  • You do not seem to set es:bx to the address of a buffer to read data into. Thus, the BIOS will read data into whatever address es:bx points to, essentially overwriting random memory.

这是一个示例,您可以通过 read 函数解决这些问题。请注意,根据您的具体情况,可能还需要进行更多更改。

Here is an example how you could fix these issues in the read function. Note that there are likely more changes needed depending on your situation.

typedef unsigned char u8;
typedef unsigned short u16;

void read(u8 sector_size, u8 track, u8 sector, u8 head, u8 drive,
    u8 *buffer, u8 *status, u8 *sectors_read)
{
    u16 result;

    asm volatile("push %%cs; pop %%es; int $0x13"
        : "=a"(result)
        : "a"(0x200|sector_size), "b"(buffer),
          "c"(track<<8|sector), "d"(head<<8|drive)
        : "es", "memory");

    *status = result >> 8;
    *sectors_read = result >> 0;
}

以上代码假定为ia16-gcc。对于i686-gcc,使用

The code above assumes ia16-gcc. For i686-gcc, use

    asm volatile("int $0x13"
        : "=a"(result)
        : "a"(0x200|sector_size), "b"(buffer),
          "c"(track<<8|sector), "d"(head<<8|drive)
        : "memory");

相反。

请理解,没有您的合作和对评论的回应人们在您的问题下写信,没有其他比这更好的帮助了。

Please understand that without your cooperation and your responses to the comments people wrote under your question, it is not possible to give any better help than this.

这篇关于无法从C中的磁盘读取扇区的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆