GCC 强行优化了我不想优化的一段代码,我让所有的东西都不稳定

GCC obtrusively optimizes one fragment of my code that I don't want to be optimized and I made everything volatile

我有函数 inportb。代码如下:

static inline volatile uint8_t inportb(volatile uint16_t port)
{
        uint8_t retval;

        asm volatile("inb %%dx,%%al" : "=a"(retval) : "dN"(port));
        return retval;
}

(outportb 的工作原理类似)

这是我的代码,它被 GCC 错误地优化了:

    // write EOI
    outportb(0x20, 0x20);

    // Lowest bit of status will be set if buffer is not empty
    if (inportb(KEYBOARD_STATUS_PORT) & 0x01) {
        keycode = inportb(KEYBOARD_DATA_PORT);
        ...

这里有 objdump:

0000000000100660 <kbd_irq>:
  100660:   b8 20 00 00 00          mov    [=12=]x20,%eax
  100665:   ba 20 00 00 00          mov    [=12=]x20,%edx
  10066a:   ee                      out    %al,(%dx)
  10066b:   ec                      in     (%dx),%al    <-- Hey! I want it to read from 0x64!
  10066c:   a8 01                   test   [=12=]x1,%al
  10066e:   0f 84 9d 00 00 00       je     100711 <kbd_irq+0xb1>
  100674:   ec                      in     (%dx),%al    <-- It should read from 0x60 here.

您的汇编语句说输入值 port 可以是 dx 或立即数。但是你没有使用实际值,而是写了 %%dx!如果编译器决定它可以是一个立即值,那么,你的汇编代码 完全忽略它 并使用 dx 无论如何。

尝试使用 %1 而不是 %%dx,这意味着第二个 input/output 值(因为它们从 0 开始)。在这种情况下,它意味着 port 输入。

或者,将 dN 更改为 d,以便值始终以 dx 为单位。