Reputation: 9429
In x86 assembly, why can we use eRx
in 16 bit "real mode", but we can't use rRx
in 32 bit mode? For example:
BITS 16
mov bx, 1
mov eax, 2
will assemble and disassemble correctly. And it works, as I have disassembled the Win2k bootloader before and found references to eax
.
However, how come there is no way, even on a 64-bit processor, in 32-bit "protected mode", you can't access rRx
?
Upvotes: 3
Views: 390
Reputation: 62048
You can't access 64-bit registers in non-64-bit modes by design, CPU design.
You can access 32-bit registers in 16-bit modes by design as well. You do this by using the special instruction prefixes called operand size prefix (0x66
) and address size prefix (0x67
).
There are no special instruction prefixes to reach 64-bit registers in non-64-bit modes.
There was not enough opcode/prefix coding space left in 32-bit mode to add that in, unlike when 386 extended 286 there were some unused bytes for prefixes.
The 0x4?
REX prefixes that are needed to specify 64-bit operand-size in 64-bit mode are inc
/dec
instructions in 32-bit and 16-bit mode. AMD64 had to change the meaning of some bytes to make room for the prefixes they wanted to. The same change to 32-bit mode would not be compatible with existing binaries.
Upvotes: 4
Reputation: 18217
The reason for this is that the 64bit mode changes instruction decoding in one particular place - namely, to enable the prefix bytes used to indicate operand sizes of 64bit / extend register width to 64bit / extend register usage to the "new" R8
..R15
registers. These are different from the "alternate size prefix" (0x66
), which is generic to x86 (independent of the CPU operating mode) and changes operand/register size from 16bit to 32bit if in 16bit mode, and vice versa from 32bit to 16bit if in 32bit mode.
The so-called REX
prefixes are encoded as 0x40
..0x4f
and are only valid as prefixes if the CPU is operating in 64bit mode. Why is that so ? Well - as said, changed instruction decoding, these opcodes actually map to one-byte versions of inc <reg>
/dec <reg>
in classical x86.
This is possible because of an ambiguity in the 16/32bit instruction set - inc EAX
can be either 0x40
or 0xff 0xc0
. In 64bit mode, the instruction decoder only accepts 0xff 0xc0
for this. On the other hand, 0x40
, as indicated, becomes one of the REX
prefixes.
Hence - these 64bit operand size prefixes do not exist in 16bit/32bit mode (they are inc
/dec
operations then ...), therefore there exists no way for 16bit/32bit x86 code to state "I'd like to do a 64bit op".
As an example, here's the assembly / opcodes for a few instructions with different operand sizes:
64bit 32bit option 1 32bit option 2 instruction ============================================================= fe c8 fe c8 -- dec al 66 ff c8 66 ff c8 66 48 dec ax ff c8 ff c8 48 dec eax 48 ff c8 -- -- dec rax
As you can see, 64bit knows no one-byte version of dec eax
, but instead it knows 0x48
as (one of several) instruction prefix(es) saying "make this a 64bit op".
Upvotes: 7
Reputation: 5884
Well, if you were using a 80286, then it would not work! The computer you are using is a 32bit CPU which has both 16bit and 32bit registers but NOT 64bit registers. It would work on a 64bit cpu also.
Upvotes: 1