我得到了错误错误:'in'的算子类型不符生成此值的行是:
inb %%eax, %%edx
我试过这些:inb %%eax, $0x00000064和inb %%eax, $0x64中的一个或多个。我也尝试用in代替inb,但是我现在还在黑暗中尝试。有什么想法吗?
inb %%eax, $0x00000064
inb %%eax, $0x64
in
inb
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
应该没问题。
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的对等语法为
in src, dst
inw
inl
inb $0x64, %al
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的答案所示:
"Nd"((uint16_t)port)
%1
%%dx
gcc -masm=intel
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扩展为%al或al,省去了编译器的麻烦。
%0
%al
al
apeeds0o3#
英特尔提供的关于i/o指令集的信息非常少。尽管如此,你还是要处理一个端口地址或一个寄存器,然后从那个地址提取输入。在目标中,源请注意,您的目标是物理地址所以你必须指出那个地址在$0x8中,%al ;
请注意,英特尔警告不要使用0 FH至0 FFH
这会将ax的低8位放入物理地址0x 8
3条答案
按热度按时间lxkprmvk1#
“inB”表示对大小为byte的操作数执行助记符命令“in”(8位). inw表示字(16位),inl用于长字(32位),inq用于四通道(在64位计算机上)。%eax寄存器为32位,由%ax(16位)。%ax寄存器依次由高8位(%ah)和低8位(%al)组成。因此,如果要使用“inb”,则应使用%al或%ah,例如:
要在%eax中使用“in”,您需要在命令后追加“l”(或者省略字母,因为某些编译器可以推断类型)。也就是说,
应该没问题。
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的对等语法为
或者更好的方法是,让编译器通过使用
"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的答案所示:让编译器根据语法模式将
%0
扩展为%al
或al
,省去了编译器的麻烦。apeeds0o3#
英特尔提供的关于i/o指令集的信息非常少。尽管如此,你还是要处理一个端口地址或一个寄存器,然后从那个地址提取输入。
在目标中,源
请注意,您的目标是物理地址
所以你必须指出那个地址
在$0x8中,%al ;
请注意,英特尔警告不要使用0 FH至0 FFH
这会将ax的低8位放入物理地址0x 8