GNU汇编语法

时间:2017-09-10 03:55:14

标签: assembly inline-assembly att

我正在编写一个内联汇编代码来读取实时时钟。我正在加载要读取的寄存器号码(4)' dl'并将其加载到端口0x70。我试图将此寄存器值(4)读入al。有关详情,请访问RTC

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

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

  

汇编程序消息:

     

错误:' out'

的操作数大小不匹配      

错误:`in'

的操作数大小不匹配

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

有人可以指出这个问题吗?

1 个答案:

答案 0 :(得分:4)

有很多问题。首先,inout只能在A寄存器(alaxeaxrax)上运行。其次,操作数顺序是错误的,第三,immediates必须以AT& T语法中的$作为前缀。在普通程序集中,您的代码应如下所示:

mov $4,%al
out %al,$0x70
in  $0x71,%al

所以你的校正装配将是

asm(
"movb $4, %%al;"
"outb %%al, $0x70;"
"inb $0x71, %%al;"
:
:
:"%al"
);

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

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

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

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