该答案是对 OP 在主要编辑之前提出的问题的第一个版本的回应。这解决了该指令的 GNU 汇编器的 AT&T 语法INS
。
INS/INSB/INSW/INSD的指令集参考——从端口输入到字符串表明实际上只有 3 种形式的 INS 指令。采用字节(B)、字(W)或双字(D)的格式。最终,从 DX 中的端口读取 BYTE( b
)、WORD( w
) 或 DWORD( l
) 并将其写入或ES:RDI、ES:EDI、ES:DI。没有任何形式的INS
指令将寄存器作为目标,不像IN
可以写入AL/AX/EAX的指令。
注意:在IN
指令中,端口被认为是源,并且是 AT&T 语法中格式为 的第一个参数instruction src, dest
。
在 GNU 汇编器中,简单地使用以下 3 种形式中的任何一种是最简单的:
insb # Read BYTE from port in DX to [RDI] or ES:[EDI] or ES:[DI]
insw # Read WORD from port in DX to [RDI] or ES:[EDI] or ES:[DI]
insl # Read DWORD from port in DX to [RDI] or ES:[EDI] or ES:[DI]
在 16 位代码中,这些指令将执行以下操作:
insb # Read BYTE from port in DX to ES:[DI]
insw # Read WORD from port in DX to ES:[DI]
insl # Read DWORD from port in DX to ES:[DI]
在 32 位代码中,这些指令将执行以下操作:
insb # Read BYTE from port in DX to ES:[EDI]
insw # Read WORD from port in DX to ES:[EDI]
insl # Read DWORD from port in DX to ES:[EDI]
在 64 位代码中,这些指令将执行以下操作:
insb # Read BYTE from port in DX to [RDI]
insw # Read WORD from port in DX to [RDI]
insl # Read DWORD from port in DX to [RDI]
为什么汇编程序也支持长格式?主要用于文档目的,但有一个细微的变化可以用长格式表示,那就是内存地址的大小(而不是要移动的数据的大小)。在 GNU 汇编器中,这在 16 位代码中得到支持:
insb (%dx),%es:(%di) # also applies to INSW and INSL
insb (%dx),%es:(%edi) # also applies to INSW and INSL
16 位代码可以使用 16 位或 32 位寄存器来形成内存操作数,这就是您可以覆盖它的方式(addr
下面描述了另一个使用覆盖)。在 32 位代码中可以这样做:
insb (%dx),%es:(%di) # also applies to INSW and INSL
insb (%dx),%es:(%edi) # also applies to INSW and INSL
可以在 32 位代码的内存操作数中使用 16 位寄存器。很少有使用案例特别有用,但处理器支持它。在 64 位代码中,您可以在内存操作数中使用 32 位或 64 位寄存器,因此在 64 位代码中这是可能的:
insb (%dx),%es:(%rdi) # also applies to INSW and INSL
insb (%dx),%es:(%edi) # also applies to INSW and INSL
在 GNU 汇编器中有一种更短的方法来更改内存地址大小,它INSB/INSW/INSL
与addr16
、addr32
和addr64
覆盖一起使用。作为 16 位代码的示例,这些是等效的:
addr32 insb # Memory address is %es:(%edi). also applies to INSW and INSL
insb (%dx),%es:(%edi) # Same as above
在 32 位代码中,这些是等效的:
addr16 insb # Memory address is %es:(%di). also applies to INSW and INSL
insb (%dx),%es:(%di) # Same as above
在 64 位代码中,这些是等效的:
addr32 insb # Memory address is %es:(%edi). also applies to INSW and INSL
insb (%dx),%es:(%edi) # Same as above