I'm developing an operating system. So far, I've added an HDD driver to my operating system that uses PIO. Here is the code in 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
Here is the file 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))
However, I can't build it. For all of lines that look like this:
outb(ctr + x, y & 0xFF)
I get an error like this:
Inconsistent operand constraints in an 'asm'.
I've read similar questions where the problem is the -fPIC
compiler flag that doesn't allow using EBX
but I use neither -fPIC
nor EBX
registers. Here's the full build log:
$ 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
What's strange is that for the same code in write_hdd_sector
, no error is shown. I've got no idea what the problem could be. How do I fix this error? Any suggestions?
答案 0 :(得分:2)
该问题与寄存器的使用无关,而与操作数的大小有关。请参阅typedef uint64_t lba48_addr_t;
,并且您的outb
内联汇编指令要求两个参数都适合32位。通过编写表格代码......
outb(ctr + x, something_that_uses_the_addr_variable & 0xFF);
该条件无法满足,因为addr
的类型为lba48_addr_t
,a.k.a uint64_t
。为了避免将来出现此类问题,您应该将outb
定义为这样的内联函数...
inline void outb(uint16_t port, uint8_t value)
{
__asm("outb %b0, %w1"
:: "a"(value), "d"(port));
}