My understanding of x86 registers say that each register can be accessed by the entire 32 bit code and it is broken into multiple accessible registers.
In this example EAX
being a 32 bit register, if we call AX
it should return the first 16 bits, and if we call AH
or AL
it should return the next 8 bits after the 16 bits and AL
should return the last 8 bits.
So my question, because I don't truly believe is this is how it operates. If we store the 32 bit value aka EAX
storing:
0000 0100 0000 1000 0110 0000 0000 0111
So if we access AX
it should return
0000 0100 0000 1000
if we read AH
it should return
0000 0100
and when we read AL
it should return
0000 0111
Is this correct? and if it is what value does AH
truly hold?
No, that's not quite right.
EAX is the full 32-bit value
AX is the lower 16-bits
AL is the lower 8 bits
AH is the bits 8 through 15 (zero-based)
So AX is composed of AH:AL halves, and is itself the low half of EAX. (The upper half of EAX isn't directly accessible as a 16-bit register; you can shift or rotate EAX if you want to get at it.)
For completeness, in addition to the above, which was based on a 32-bit CPU, 64-bit Intel/AMD CPUs have
RAX, which hold a 64-bit value, and where EAX is mapped to the lower 32 bits.
All of this also applies to EBX/RBX, ECX/RCX, and EDX/RDX. The other registers like EDI/RDI have a DI low 16-bit partial register, but no high-8 part, and the low-8 DIL is only accessible in 64-bit mode: Assembly registers in 64-bit architecture
Writing AL, AH, or AX merges into the full AX/EAX/RAX, leaving other bytes unmodified for historical reasons. (In 32 or 64-bit code, prefer a movzx eax, byte [mem]
or movzx eax, word [mem]
load if you don't specifically want this merging: Why doesn't GCC use partial registers?)
Writing EAX zero-extends into RAX. (Why do x86-64 instructions on 32-bit registers zero the upper part of the full 64-bit register?)