【发布时间】:2018-09-16 22:54:38
【问题描述】:
对于上下文,我是 x86 打高尔夫球。
00000005 <start>:
5: e8 25 00 00 00 call 2f <cube>
a: 50 push %eax
稍后多次调用...
0000002f <cube>:
2f: 89 c8 mov %ecx,%eax
31: f7 e9 imul %ecx
33: f7 e9 imul %ecx
35: c3 ret
call 占用了 5 个字节,即使偏移量适合单个字节!有什么方法可以编写call cube 并使用 GNU 汇编器进行汇编并获得更小的偏移量?我知道可以使用 16 位偏移量,但理想情况下我会有一个像 call reg 这样的 2 字节指令。
【问题讨论】:
-
当前 x86 指令集中没有 2 字节
call等价于jmp。替代方案(弄乱堆栈)会更长或更长。 -
@usr2564301 我可以将我的标签地址移动到寄存器中并使用
FF调用吗? -
一次性使用也不会更短。您不能在
call reg中编码相对 地址,因此加载寄存器本身将以完全相同的长度开始——然后您需要调用它。如果这种跳跃发生得更多,它可能会在第 5 次或第 6 次调用左右时开始获得回报。 -
是的,如果您可以在寄存器中生成少于 3 个字节的完整地址...即使是相对于 RIP 的 LEA 也无济于事,因为它仅以
rel32形式存在,而不是rel8。大多数操作系统不允许您在最低页面中映射任何内容(因此 NULL 指针取消引用错误),因此可用地址大于 16 位,在 16 位模式之外。 -
@PeterCordes 我多次使用这个调用,所以即使将地址放入寄存器需要几个字节,我们也会整体保存。您可以发布答案吗?
标签: assembly x86 call micro-optimization machine-code