x86/x64 Add Displacement addressing
Solution 1
There are a few different forms of indirect operands in x86:
- [reg]
- [reg + displacement]
- [displacement]
- [reg * constant + reg]
- [reg * constant + reg + displacement]
The "displacement" is just a constant that gets added to the rest of the address. In cases where there is no component of the address other than the constant, it is still called a "displacement". This is mainly for consistency with the other addressing forms.
Another way to look at it is that all addresses are of the form
[reg * constant + reg + displacement]
With each of the components allowing a value of 0.
The [displacement] form is just the encoding where all components other than the displacement are zero.
As a compiler writer the last 2 forms are particularly interesting. They make it easy to encode things like pArray[index]->field + 1
in a single instruction.
Solution 2
There is no "special add that takes a displacement", that page is being unnecessarily confusing - this is just part of the normal memory operand encoding.
add
is a fairly standard instruction that is encoded the same way as all the alu-ops are: there is a special case for using al
as destination and an immediate as the source (04 ib
), using ax/eax/rax
as the destination and an immediate as the source (+ 05 imm
), three versions of add r/m, imm
(one for 8bit destinations, one for wider destinations and a sign-extended 8bit source, one for wider destinations and a wide source), and of course an add r, r/m
and add r/m, r
.
This is just a special case of add r, r/m
, where the r/m
takes the form of a displacement: see note #1 of ModRM encoding.
So they just mean add edx, [sdword]
. (but they misencoded the reg field, edx
corresponds to 010
, not 011
)
Solution 3
That page is not accurate. The "add that takes a displacement" which it's talking about refers to the form add r[16|32], r/m[16|32]
or add edx, [0xdisp]
as you might see it in a disassembler's output. Assuming it's talking about the ADD instruction with opcode 0x03
,
- Encoding the
edx
register destination and specifying a 32-bit displacement as effective address in the ModR/M byte would give it the value of 0x15 (refer to the Intel® 64 and IA-32 Architectures Software Developer’s Manual Vol. 2, page 41, table 2-2). - The effect of this instruction is to add the dword at the memory address
disp
to the contents ofedx
. - The actual encoding of the instruction would thus be:
\x03\x15\x00\x00\x00\x01
, for a displacement of 1 byte.
Ryan Brown
Updated on July 29, 2022Comments
-
Ryan Brown almost 2 years
I'm writing a compiler for x86/x64 CPU instructions and I can't seem to figure out what people mean by 'displacement' address. For example the Add instruction is detailed here: http://www.c-jump.com/CIS77/CPU/x86/X77_0150_encoding_add_edx_displacement.htm
I'm just trying to implement the add instruction where a register is added to a normal memory address. The problem is, the address is a 'displacement address'. Does that mean the address is a signed value that's the offset from the instruction location?
-
Ryan Brown over 11 yearsSo to add say AL (8 bit register 0) to the memory location 0x00000000, the CPU would accept (in hex) 00 05 00000000?
-
Ryan Brown over 11 yearsOk so how does [reg * constant + reg + displacement] get encoded into a machine instruction? Say I have an array at memory location 0x00000001 and I want to access the index of it which is AL. I guess I want to use the move instruction and do MOV AH 0x00000001[AL]. I think that's just [reg+displacement]. Section 6 of this page shows encoding the R/M byte but it's really confusing: c-jump.com/CIS77/CPU/x86/lecture.html
-
Scott Wisniewski over 11 yearsTake a look at volume 2 of the intel manual. Each instruction specifies its encoding forms. Encoding forms that list r/m operands accept register or memory operands in the mod/rm byte.
-
Scott Wisniewski over 11 yearsTake a look at volume 2 of the intel manual. Each instruction specifies its encoding forms. Encoding forms that list r/m operands accept register or memory operands in the mod/rm byte. In chapter 2 of volume 2, section 2.1 there is a table that shows the meaning of the mod r/m byte. The forms that have [--][--] listed denote an encoding that uses the SIB byte. SIB addressing is of the form regconstant + reg. Some forms of the mod/rm byte indicate that the SIB byte is followed by a displacement. Those gives the regconstant + reg + constant forms. There is a table explaining SIB as well.
-
Ryan Brown over 11 yearsOh ok thanks! I'm also reading that on 64-bit processors the displacement address is still 32 bits?? So on anything larger you have to load it into a register to read it?
-
Bulat M. over 7 years@Scott, Could one use register as a displacement? While assembling
lea %rax(%r12), %r14
gcc spitsError: junk (%r12) after register
. -
Scott Wisniewski over 7 yearsNo. It wouldn't be a "displacement" if it was a register. The displacement is a constant that follows the modrm byte. You can use the sum of 2 registers though. Take a look at the intel manual.