我正在使用i686-elf-gcc
交叉编译器来生成以实模式运行的代码。
我正在尝试从内核中读取一个扇区。我知道这是我的内核所在的位置,在第二个扇区中,第0个驱动器,第0个磁道。它构建良好,但是在我调用read之后,扇区读取仍为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) : );
}
答案 0 :(得分:2)
read
函数存在很多问题。由于您尚未发布可复制的示例,甚至没有足够的详细信息来了解您要针对哪种工具链进行编程,因此我无法就您的问题给出确切的答案。这是很多错误的地方:
status
中分配给sectors_read
和read
不会影响您在被叫方中传递的参数。而是传递一个指针。ax
,cx
和dx
或这些寄存器的内容很重要。因此,编译器可能将它们用于任何其喜欢的目的,从而干扰您想要的语义。要解决此问题,请使用寄存器约束而不是mov
指令将参数放入正确的寄存器中。es:bx
设置为要读取数据的缓冲区的地址。因此,BIOS会将数据读到es:bx
指向的任何地址中,实际上将覆盖随机存储器。这是一个示例,您可以如何在read
函数中解决这些问题。请注意,根据您的情况,可能还需要进行其他更改。
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,请使用
asm volatile("int $0x13"
: "=a"(result)
: "a"(0x200|sector_size), "b"(buffer),
"c"(track<<8|sector), "d"(head<<8|drive)
: "memory");
相反。
请理解,没有您的合作和对别人在您的问题下发表的评论的回应,将无法提供比这更好的帮助。