【发布时间】: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