Based on my understanding, %eax means the value contained by eax and (%eax) means go to the address reserved by eax
seta20.1:
inb $0x64, %al # Wait for not busy
testb $0x2, %al
jnz seta20.1
movb $0xd1,%al # 0xd1 −> port 0x64
outb %al, $0x64
Then, why there is no parentheses wrapping around %al? Cuz if I want to move a val to an address by using register, i should do:
mov %ebx, (%eax)
right?
inb
is basically a load from IO space, into %al
. So the analogy would be mov (%edx), %al
.
%al
is the source (out
) or destination (in
) register, not a pointer, so of course there are never parens around %al
.
If there were going to be parens anywhere, it would be around the IO space address, e.g. (%dx)
. Or 0x64()
.
But inb
/ outb
don't use normal addressing modes, they uses an immediate or %dx
for the IO-space address. So AT&T syntax uses immediate or register syntax for them in the outb destination or inb source. IO space is special and can't be addressed the same way as memory.
AT&T disassembly by objdump -d
bizarrely does use (%dx)
for the port number in the non-immediate form, but GAS accepts %dx
or (%dx)
on input which is handy for inline asm.
And both assemble to the same machine code, of course; there is only one form of the instruction using DX at all with byte operand-size: https://www.felixcloutier.com/x86/in.
0: ec in (%dx),%al
llvm-objdump -d
uses inb %dx, %al
(%dx)
is never a valid memory addressing mode: it's a 16-bit register other than BX,BP, SI or DI.