【问题标题】:GCC error message in outb macrooutb 宏中的 GCC 错误消息
【发布时间】: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中的相同代码,没有显示错误。我不知道问题可能是什么。如何修复此错误?有什么建议吗?

【问题讨论】:

  • 尝试转换为字节而不是 &amp; 0xff。我假设 lba48_t 是 64 位的数量,因此不符合约束条件。
  • @Jester 谢谢!如果您发布答案,我会将其标记为正确。
  • 请注意,您甚至不需要&amp;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


【解决方案1】:

问题与寄存器的使用无关,而与操作数的大小有关。看,你 typedef uint64_t lba48_addr_t; 和你的 outb 内联汇编指令要求两个参数都适合 32 位。通过编写形式的代码...

outb(ctr + x, something_that_uses_the_addr_variable & 0xFF);

该条件无法满足,因为addr 的类型是lba48_addr_t,也就是uint64_t。为了避免将来出现此类问题,您应该将outb 定义为像这样的内联函数...

inline void outb(uint16_t port, uint8_t value)
{
    __asm("outb %b0, %w1"
        :: "a"(value), "d"(port));
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-29
    • 2020-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多