【发布时间】:2016-02-16 18:59:47
【问题描述】:
我正在开发一个操作系统。到目前为止,我已经在使用 PIO 的操作系统中添加了一个 HDD 驱动程序。这是hdd.h中的代码:
#ifndef HDD_H_INCLUDED
#define HDD_H_INCLUDED
#include "includes.h"
typedef uint64_t lba48_addr_t;
typedef uint16_t ide_ctr_t;
typedef uint16_t ide_disk_t;
#define MASTER 0x1F0
#define SLAVE 0x170
void read_hdd_sector(ide_ctr_t ctr, ide_disk_t disk, lba48_addr_t addr, void* dst);
void write_hdd_sector(ide_ctr_t ctr, ide_disk_t disk, lba48_addr_t addr, void* src);
#endif // HDD_H_INCLUDED
这里是文件hdd.c:
#include "includes.h"
void read_hdd_sector(ide_ctr_t ctr, lba48_addr_t addr, void* dst) {
outb(ctr + 6, disk == MASTER ? 0x40 : 0x50);
outb(ctr + 2, 0x00);
outb(ctr + 3, (addr >> 24) & 0xFF);
outb(ctr + 4, (addr >> 32) & 0xFF);
outb(ctr + 5, (addr >> 40) & 0xFF);
outb(ctr + 2, 0x01);
outb(ctr + 3, addr & 0xFF);
outb(ctr + 4, (addr >> 8) & 0xFF);
outb(ctr + 5, (addr >> 16) & 0xFF);
outb(ctr + 7, 0x24);
uint8_t sig = 0;
while(!(sig & 0x08)) {
inb(0x1F7, sig);
}
for(int ix = 0; ix < 256; ix++) {
uint16_t word;
inw(0x1F0, word);
*((uint16_t*)(dst + idx * 2)) = word;
}
}
void write_hdd_sector(ide_ctr_t ctr, lba48_addr_t addr, void* src) {
outb(ctr + 6, disk == MASTER ? 0x40 : 0x50);
outb(ctr + 2, 0x00);
outb(ctr + 3, (addr >> 24) & 0xFF);
outb(ctr + 4, (addr >> 32) & 0xFF);
outb(ctr + 5, (addr >> 40) & 0xFF);
outb(ctr + 2, 0x01);
outb(ctr + 3, addr & 0xFF);
outb(ctr + 4, (addr >> 8) & 0xFF);
outb(ctr + 5, (addr >> 16) & 0xFF);
outb(ctr + 7, 0x34);
uint8_t sig = 0;
while(!(sig & 0x08)) {
inb(0x1F7, sig);
}
for(int ix = 0; ix < 256; ix++) {
outw(0x1F0, *((uint16_t*)(src + idx * 2)));
}
}
#define outb(port, value) __asm("outb %b0, %w1" : : "a" (value), "d" (port))
但是,我无法构建它。对于所有看起来像这样的行:
outb(ctr + x, y & 0xFF)
我收到这样的错误:
“asm”中的操作数约束不一致。
我读过类似的问题,问题是 -fPIC 编译器标志不允许使用 EBX 但我既不使用 -fPIC 也不使用 EBX 寄存器。这是完整的构建日志:
$ make
/home/alexander/opt/cross/bin/i686-elf-gcc -ffreestanding -Wall -Wextra -Werror -std=c11 -Iinclude -g -c hdd.c -o hdd.c.o
In file included from include/includes.h:10:0,
from hdd.c:1:
hdd.c: In function 'read_hdd_sector':
include/system.h:7:27: error: inconsistent operand constraints in an 'asm'
#define outb(port, value) __asm("outb %b0, %w1" : : "a" (value), "d" (port))
^
hdd.c:6:5: note: in expansion of macro 'outb'
outb(ctr + 3, (addr >> 24) & 0xFF);
^
include/system.h:7:27: error: inconsistent operand constraints in an 'asm'
#define outb(port, value) __asm("outb %b0, %w1" : : "a" (value), "d" (port))
^
hdd.c:7:5: note: in expansion of macro 'outb'
outb(ctr + 4, (addr >> 32) & 0xFF);
^
include/system.h:7:27: error: inconsistent operand constraints in an 'asm'
#define outb(port, value) __asm("outb %b0, %w1" : : "a" (value), "d" (port))
^
hdd.c:8:5: note: in expansion of macro 'outb'
outb(ctr + 5, (addr >> 40) & 0xFF);
^
include/system.h:7:27: error: inconsistent operand constraints in an 'asm'
#define outb(port, value) __asm("outb %b0, %w1" : : "a" (value), "d" (port))
^
hdd.c:10:5: note: in expansion of macro 'outb'
outb(ctr + 3, addr & 0xFF);
^
include/system.h:7:27: error: inconsistent operand constraints in an 'asm'
#define outb(port, value) __asm("outb %b0, %w1" : : "a" (value), "d" (port))
^
hdd.c:11:5: note: in expansion of macro 'outb'
outb(ctr + 4, (addr >> 8) & 0xFF);
^
include/system.h:7:27: error: inconsistent operand constraints in an 'asm'
#define outb(port, value) __asm("outb %b0, %w1" : : "a" (value), "d" (port))
^
hdd.c:12:5: note: in expansion of macro 'outb'
outb(ctr + 5, (addr >> 16) & 0xFF);
^
make: *** [hdd.c.o] Error 1
奇怪的是write_hdd_sector中的相同代码,没有显示错误。我不知道问题可能是什么。如何修复此错误?有什么建议吗?
【问题讨论】:
-
尝试转换为字节而不是
& 0xff。我假设lba48_t是 64 位的数量,因此不符合约束条件。 -
@Jester 谢谢!如果您发布答案,我会将其标记为正确。
-
-
请注意,您甚至不需要
&0xff。理想情况下,gcc 会编写像outb %al, $40/shr $16, %eax/outb %al, $42这样的代码。您的代码最多可以让 gcc 在每个out之前移入另一个寄存器和mov %somewhere, %al。 (也许利用mov %dh, %al和类似的优势)。在最坏的情况下,每次轮班后复印和蒙版。如果您将端口的约束写为"di",则可以通过避免将值放入dx的额外指令来节省代码大小。 -
@PeterCordes :我通常使用“Nd”约束。
标签: c gcc assembly gnu-assembler osdev