This is a question about the operand-size override prefixes in the x86-64 (AMD64) architecture.
Here is a bunch of assembler instructions (nasm) and their encodings; by new I mean the r8, ..., r15 registers:
67: address-size override prefix
|
| 4x: operand-size override prefix
| |
; Assembler ; | Dst operand | Src operand | -- --
mov eax,ecx ; | 32-bit | 32-bit | 89 C8 |
mov r8d,ecx ; | 32-bit new | 32-bit | 41 89 C8 |
mov eax,r9d ; | 32-bit | 32-bit new | 44 89 C8 |
mov r8d,r9d ; | 32-bit new | 32-bit new | 45 89 C8 |
mov rax,rcx ; | 64-bit | 64-bit | 48 89 C8 |
mov r8,rcx ; | 64-bit new | 64-bit | 49 89 C8 |
mov rax,r9 ; | 64-bit | 64-bit new | 4C 89 C8 |
mov r8,r9 ; | 64-bit new | 64-bit new | 4D 89 C8 |
lea eax,[ecx] ; | 32-bit | 32-bit | 67 8D 01 |
lea r8d,[ecx] ; | 32-bit new | 32-bit | 67 44 8D 01 |
lea eax,[r9d] ; | 32-bit | 32-bit new | 67 41 8D 01 |
lea r8d,[r9d] ; | 32-bit new | 32-bit new | 67 45 8D 01 |
lea rax,[rcx] ; | 64-bit | 64-bit | 48 8D 01 |
lea r8,[rcx] ; | 64-bit new | 64-bit | 4C 8D 01 |
lea rax,[r9] ; | 64-bit | 64-bit new | 49 8D 01 |
lea r8,[r9] ; | 64-bit new | 64-bit new | 4D 8D 01 |
push rax ; | | 64-bit | 50 |
push r8 ; | | 64-bit new | 41 50 |
From studying these and the same instructions with other registers, I deduce the following. There is a pairing between ‘old’ and ‘new’ registers. Non-exhaustively:
AX <--> R8
CX <--> R9
DX <--> R10
BX <--> R11
BP <--> R13
Ignoring the size prefix, the instruction bytes do not refer to particular registers, but to pairs of registers. As an example: the bytes 89 C8 indicate a mov instruction from a source which is either ecx, rcx, r9d, or r9, to a destination which is either eax, rax, r8d, or r8. Given that the operands must be both 32- or 64-bits wide, there are eight legal possible combinations. The operand-size override prefix (or absence thereof) indicates which of those combinations is the intended one. For instance if the prefix is present and is 44, then the source operand must be a 32-bit new register (in this example then collapsing to r9d) and the destination must be a 32-bit old register (here then signalling eax).
I may not have got it totally right, but I think I get the gist of it. It would appear then that what the operand-size override prefixes do override is the fact that without them the instruction would use 32-bit ‘old’ operands.
But for sure, there is something that escapes me, otherwise: what sense then does it make to talk about “a version of x86-64 with a default operand-size of 64-bit” (like here)?
Or is there a way, running on a 64-bit machine, to set the default operand size to either 32 or 64, and if so, and if my program set the machine appropriately, I would see different encodings?
Also: when would the 66H operand-size override prefix be used?
40h
to4Fh
prefixes are called REX prefixes. They can indicate 64-bit operand size. They can also indicate to use one of the upper 8 registers for the source or the destination. Any combination of these options is possible I believe. – Bibliographysil
,dil
,spl
, andbpl
instead ofah
,ch
,dh
, andbh
. – Babul