【问题标题】:GCC obtrusively optimizes one fragment of my code that I don't want to be optimized and I made everything volatileGCC 突兀地优化了我不想优化的代码片段,我让一切都变得不稳定
【发布时间】:2021-06-26 09:19:24
【问题描述】:

我有函数 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    $0x20,%eax
  100665:   ba 20 00 00 00          mov    $0x20,%edx
  10066a:   ee                      out    %al,(%dx)
  10066b:   ec                      in     (%dx),%al    <-- Hey! I want it to read from 0x64!
  10066c:   a8 01                   test   $0x1,%al
  10066e:   0f 84 9d 00 00 00       je     100711 <kbd_irq+0xb1>
  100674:   ec                      in     (%dx),%al    <-- It should read from 0x60 here.

【问题讨论】:

  • 也许#pragma GCC optimize 0 可以帮忙?见gcc.gnu.org/onlinedocs/gcc/…
  • 神奇的数字 0x64 和 0x60 是从哪里来的?
  • 你确定没有把KEYBOARD_STATUS_PORT和KEYBOARD_DATA_PORT设置为0x20吗?
  • 你确定 dN 是正确的吗? d 表示它应该在 dx 寄存器中,但 N 表示它应该是一个立即数。也许这种组合会让编译器感到困惑。
  • @user253751 你是对的。我对汇编器内联没有经验。 “dN”应该是正常功能,但后来我把它变成了内联,现在它应该只是“d”。

标签: c gcc compiler-optimization


【解决方案1】:

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

尝试使用%1 代替%%dx,这意味着第二个输入/输出值(因为它们从0 开始)。在这种情况下,它表示port 输入。

或者,将dN 更改为d,以便该值始终在 dx 中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-27
    • 2016-01-01
    • 2011-12-16
    • 2010-11-02
    • 1970-01-01
    • 2021-02-14
    • 1970-01-01
    • 2011-07-31
    相关资源
    最近更新 更多