为什么 AT&T 语法在 IN / OUT 指令中使用 DX 周围的括号,如 inb (%dx),%al
Why does AT&T syntax use parens around DX in IN / OUT instructions like inb (%dx),%al
7c6f: ec in (%dx),%al
这里我的疑惑是由于()
我写代码的很多地方都可以使用 (%dx)
中的值并将其用作内存位置,并且值位于需要的值处。
但这里应该只是 in %dx,%al
;和 %dx 保持端口号
就像in 0x000,al
你的问题比较不清楚,我会尽力回答的。
使用 (%dx)
作为第一个操作数并不像您想象的那样工作; in
和 out
,
(%dx)
是 不是 内存操作数,这与其他指令的操作数使用相同语法的方式不同。
IN
指令有两个操作数:
立即数 8 位值(如 [=16=]x42
)或 DX
寄存器。
AL
、AX
或 EAX
.
这意味着您不能为任一操作数使用内存位置。
此外,如@PeterCordes 的回答所示,使用 %dx
作为内存地址永远无效。
由于这两个原因,(%dx)
不能被解释为内存地址,因此您的汇编程序会忽略括号并将其单独解释为寄存器 %dx
。
也就是说in (%dx),%al
和in %dx,%al
完全一样。
如果要从存储在内存中的端口号获取输入,必须先将值加载到 %dx
寄存器:
mov (%something),%dx
in %dx,%al
有关详细信息,请参阅 Intel IA-32 reference manual, or this reference page 的 2A 卷 3-494 页。
in %dx, %al
汇编成相同的 0xEC
字节机器码,objdump -d
反汇编成 in (%dx),%al
,如您所见。
llvm-objdump -d
确实使用了您期望的语法:inb %dx, %al
; inb 8, %al
AT&T 语法使用 (%dx)
作为 in
/ out
中的 IO 端口号是一种误导,因为它不是正常的寻址模式; DX 是唯一的选择。大概 想要表示您正在读取或写入 I/O 地址 space 的事实。但是他们做得不好,因为这与他们对直接端口号使用 in [=21=]x80, %al
不一致(与使用与绝对内存地址相同的语法的端口号 0x80
相反)。 GAS 和 LLVM 甚至不接受 in 0x80, %al
,所以不,不是“就像 in 0x000,al
”。
in
/out
指令访问IOspace,不是内存地址space。
IO space 中的“地址”称为端口号。
IOspace在现代PCI-express中仍然是一个东西,但是大多数现代设备在设备内存区域中只有MMIO寄存器,而不是IO端口,因为IO端口访问速度较慢。
objdump -drwC -Mintel
反汇编为英特尔在 their manual entry 中使用的相同语法,用于 in
的唯一形式,它在 DX 和字节 operand-size 中有一个端口。注意缺少 [dx]
括号。
0: ec in al,dx
1: e4 80 in al,0x80
(%dx)
是 ,因此特定寻址模式对任何其他指令都无效。但是,是的,(%reg)
例如 (%edx)
或 (%bx)
是 AT&T addressing-mode 指令中内存操作数的语法,它允许正常的 reg/mem
操作数,例如 mov
或 add
.
另见
7c6f: ec in (%dx),%al
这里我的疑惑是由于()
我写代码的很多地方都可以使用 (%dx)
中的值并将其用作内存位置,并且值位于需要的值处。
但这里应该只是 in %dx,%al
;和 %dx 保持端口号
就像in 0x000,al
你的问题比较不清楚,我会尽力回答的。
使用 (%dx)
作为第一个操作数并不像您想象的那样工作; in
和 out
,
(%dx)
是 不是 内存操作数,这与其他指令的操作数使用相同语法的方式不同。
IN
指令有两个操作数:
立即数 8 位值(如
[=16=]x42
)或DX
寄存器。AL
、AX
或EAX
.
这意味着您不能为任一操作数使用内存位置。
此外,如@PeterCordes 的回答所示,使用 %dx
作为内存地址永远无效。
由于这两个原因,(%dx)
不能被解释为内存地址,因此您的汇编程序会忽略括号并将其单独解释为寄存器 %dx
。
也就是说in (%dx),%al
和in %dx,%al
完全一样。
如果要从存储在内存中的端口号获取输入,必须先将值加载到 %dx
寄存器:
mov (%something),%dx
in %dx,%al
有关详细信息,请参阅 Intel IA-32 reference manual, or this reference page 的 2A 卷 3-494 页。
in %dx, %al
汇编成相同的 0xEC
字节机器码,objdump -d
反汇编成 in (%dx),%al
,如您所见。
llvm-objdump -d
确实使用了您期望的语法:inb %dx, %al
; inb 8, %al
AT&T 语法使用 (%dx)
作为 in
/ out
中的 IO 端口号是一种误导,因为它不是正常的寻址模式; DX 是唯一的选择。大概 in [=21=]x80, %al
不一致(与使用与绝对内存地址相同的语法的端口号 0x80
相反)。 GAS 和 LLVM 甚至不接受 in 0x80, %al
,所以不,不是“就像 in 0x000,al
”。
in
/out
指令访问IOspace,不是内存地址space。
IO space 中的“地址”称为端口号。
IOspace在现代PCI-express中仍然是一个东西,但是大多数现代设备在设备内存区域中只有MMIO寄存器,而不是IO端口,因为IO端口访问速度较慢。
objdump -drwC -Mintel
反汇编为英特尔在 their manual entry 中使用的相同语法,用于 in
的唯一形式,它在 DX 和字节 operand-size 中有一个端口。注意缺少 [dx]
括号。
0: ec in al,dx
1: e4 80 in al,0x80
(%dx)
是 (%reg)
例如 (%edx)
或 (%bx)
是 AT&T addressing-mode 指令中内存操作数的语法,它允许正常的 reg/mem
操作数,例如 mov
或 add
.
另见