我正在为x86 / x64 CPU指令编写一个编译器,我似乎无法弄清楚“置换”地址的含义。例如,这里详细说明了Add指令: http://www.c-jump.com/CIS77/CPU/x86/X77_0150_encoding_add_edx_displacement.htm
我只是尝试实现add指令,其中寄存器被添加到正常的内存地址。问题是,地址是“位移地址”。这是否意味着地址是一个有符号的值,它是指令位置的偏移量?
答案 0 :(得分:10)
x86中有几种不同形式的间接操作数:
“displa”只是一个常量,会被添加到地址的其余部分。如果除了常量之外没有地址的组成部分,它仍称为“位移”。这主要是为了与其他寻址形式保持一致。
另一种看待它的方法是所有地址都是
形式[reg * constant + reg + displacement]
每个组件允许值为0。
[displacement]形式只是编码,其中除位移之外的所有组件都为零。
作为编译器编写者,最后两种形式特别有趣。它们可以轻松地在单个指令中对pArray[index]->field + 1
之类的内容进行编码。
答案 1 :(得分:4)
没有“特殊添加占用位移”,该页面不必要地混淆 - 这只是普通内存操作数编码的一部分。
add
是一个相当标准的指令,其编码方式与所有alu-ops相同:有一种特殊情况,可以使用al
作为目标,使用immediate作为源({{ 1}}),使用04 ib
作为目的地,使用立即作为源(ax/eax/rax
),使用+ 05 imm
的三个版本(一个用于8位目的地,一个用于更广泛的目的地和一个标志 - 扩展的8位源,一个用于更广泛的目的地和广泛的来源),当然还有add r/m, imm
和add r, r/m
。
这只是add r/m, r
的特例,其中add r, r/m
采用置换形式:请参阅ModRM encoding的注释#1。
所以他们只是指r/m
。 (但他们错误编码了注册字段,add edx, [sdword]
对应edx
,而不是010
)
答案 2 :(得分:4)
该页面不准确。它正在讨论的“添加取一个位移”指的是add r[16|32], r/m[16|32]
或add edx, [0xdisp]
形式,因为您可能会在反汇编程序的输出中看到它。假设它正在讨论带有操作码0x03
的ADD指令,
edx
寄存器目的地进行编码并将32位位移指定为ModR / M字节中的有效地址将使其值为0x15(请参阅英特尔®64和IA-32架构软件开发人员手册第2卷,第41页,表2-2)。disp
的dword添加到edx
的内容。\x03\x15\x00\x00\x00\x01
,位移为1个字节。