问题
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?
回答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.
回答2:
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.
回答3:
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
)
来源:https://stackoverflow.com/questions/13329611/x86-x64-add-displacement-addressing