我正在编写一个x86/x64 CPU指令的编译器,但我似乎无法理解人们所说的“位移”地址。例如,这里详细介绍了Add指令:
http://www.c-jump.com/CIS77/CPU/x86/X77_0150_encoding_add_edx_displacement.htm
我只是想实现将寄存器加到普通内存地址的add指令。问题是,该地址是一个“位移地址”。这是否意味着该地址是从指令位置偏移的带符号值?
x86架构中有几种不同形式的间接操作数:
“位移(displacement)”只是一个常量,它会被添加到地址的其余部分。在除常量外没有其他地址组成部分的情况下,仍称其为“位移”。这主要是为了与其他寻址形式保持一致。
另一种看待它的方式是,所有地址都采用以下格式:
[reg * constant + reg + displacement]
每个组件都允许值为0。
[displacement]格式只是编码时,除了位移以外的所有组件均为零。
作为编译器编写者,最后两种形式特别有趣。它们使得像pArray [index] -> field + 1
这样的东西可以在单条指令中轻松编码。
lea %rax(%r12), %r14
时,gcc会报错“Error: junk (%r12) after register”。 - anonadd r[16|32], r/m[16|32]
或add edx, [0xdisp]
,你可能在反汇编输出中看到它。假设它是在讨论带有操作码0x03
的ADD指令,
edx
寄存器目的地进行编码,并指定一个32位位移作为有效地址,将使其值为0x15(参见Intel® 64和IA-32体系结构软件开发人员手册第2卷,第41页,表2-2)。disp
处的双字加到edx
的内容中。\x03\x15\x00\x00\x00\x01
,对于1字节的位移。