assembly 内嵌asm:'in'的算子类型不符

mlmc2os5  于 2022-11-13  发布在  其他
关注(0)|答案(3)|浏览(176)

我得到了错误
错误:'in'的算子类型不符
生成此值的行是:

inb %%eax, %%edx

我试过这些:inb %%eax, $0x00000064inb %%eax, $0x64中的一个或多个。
我也尝试用in代替inb,但是我现在还在黑暗中尝试。
有什么想法吗?

lxkprmvk

lxkprmvk1#

“inB”表示对大小为byte的操作数执行助记符命令“in”(8位). inw表示字(16位),inl用于长字(32位),inq用于四通道(在64位计算机上)。%eax寄存器为32位,由%ax(16位)。%ax寄存器依次由高8位(%ah)和低8位(%al)组成。因此,如果要使用“inb”,则应使用%al或%ah,例如:

inb %%al, %%dl # from source %%al 8-bit to destination %%dl 8-bit.

要在%eax中使用“in”,您需要在命令后追加“l”(或者省略字母,因为某些编译器可以推断类型)。也就是说,

inl %%eax, %%edx

应该没问题。

rsl1atfo

rsl1atfo2#

AT&T的语法是in src, dst,其中src是端口号,目标是AL、AX、EAX,具体取决于您要进行的I/O访问的大小。(inb/inw/inl)。即使在64位模式下,64位IO大小也 * 不可 * 用。
端口号可以是立即数,如inb $0x64, %al,但如果是寄存器,则必须是DX。
(I/O地址是16位的,与物理或虚拟地址空间分开)。
https://www.felixcloutier.com/x86/in- Intel的手册使用Intel语法,因此AT&T的对等语法为

asm volatile("inb %%dx, %%al" : "=a"(byte) : "d"(portnum));

或者更好的方法是,让编译器通过使用"Nd"((uint16_t)port)约束为您选择立即数和寄存器,并使用%1操作数而不是硬编码%%dx
请参阅Porting AT&T inline-asm inb / outb wrappers to work with gcc -masm=intel,了解AT& T语法 Package 函数的工作情况,以及英特尔语法 Package 函数的工作情况。
为了让它也能和gcc -masm=intel一起工作,你可以使用dialect alternatives,如Michael Petch的答案所示:

uint8_t inb(uint16_t port)
{
    uint8_t ret;  // 8-bit type will get "=a" to pick AL
    asm volatile ( "inb {%[port], %[retreg] | %[retreg], %[port]}"
                   : [retreg]"=a"(ret)
                   : [port]"Nd"(port) );
    return ret;
}

让编译器根据语法模式将%0扩展为%alal,省去了编译器的麻烦。

apeeds0o

apeeds0o3#

英特尔提供的关于i/o指令集的信息非常少。尽管如此,你还是要处理一个端口地址或一个寄存器,然后从那个地址提取输入。
在目标中,源
请注意,您的目标是物理地址
所以你必须指出那个地址
在$0x8中,%al ;

请注意,英特尔警告不要使用0 FH至0 FFH

这会将ax的低8位放入物理地址0x 8

相关问题