Search code examples
assemblyx86att

Why there is no parentheses wrapping around AL register?


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?


Solution

  • 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.