IN 和 OUT 指令的 GNU 汇编程序语法

GNU assembler syntax for IN and OUT instructions

我正在编写内联汇编代码来读取实时时钟。我正在将要读取的寄存器号 (4) 加载到 'dl' 并将其加载到端口 0x70。我正在尝试将此寄存器值(4)读入 al。更多信息 - RTC

asm(
"mov , %%dl;"
"out 0x70, %%dl;"
"in %%al, 0x71;"
:
:
:"%al","%dl"
);

我在编译包含此代码的 c 文件时收到以下错误消息。

Assembler messages:

Error: operand size mismatch for 'out'

Error: operand size mismatch for `in'

汇编器版本:GNU 汇编器版本 2.26.1 (x86_64-linux-gnu) 使用 BFD 版本 (GNU Binutils for Ubuntu) 2.26.1

有人可以指出问题吗?

有很多问题。首先,inout都只能对A寄存器进行操作(alaxeaxrax)。第二,操作数顺序错误,第三,在 AT&T 语法中,立即数必须以 $ 为前缀。在普通汇编中,您的代码应如下所示:

mov ,%al
out %al,[=10=]x70
in  [=10=]x71,%al

因此您更正后的程序集将是

asm(
"movb , %%al;"
"outb %%al, [=11=]x70;"
"inb [=11=]x71, %%al;"
:
:
:"%al"
);

请注意,我添加了明确的大小后缀以帮助 clang assemble 这段代码。我建议您进一步修改此代码以使用正确的扩展内联汇编:

unsigned char result;
volatile asm("outb %1,[=12=]x70; inb [=12=]x71, %0" : "=a"(result) : "a"((char)4));

这可以使 gcc 生成稍微更好的代码。例如,它允许 gcc 内联这段代码。

此外,您可以考虑使用 <sys/io.h> 中的 inb()outb() 宏来完全避免内联汇编。这通常是一件非常好的事情。