更短的 x86 调用指令
Shorter x86 call instruction
就上下文而言,我正在打 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 个字节,即使偏移量适合一个字节!有什么办法可以用 GNU assembler 编写 call cube
和 assemble 并获得更小的偏移量吗?我知道可以使用 16 位偏移量,但理想情况下我会使用像 call reg
这样的 2 字节指令。
没有 call rel8
,也没有任何方法可以将 return 地址和 jmp
推送到少于 5 个字节。
要在 call reg
中脱颖而出,您需要在寄存器中生成一个少于 3 个字节的完整地址。即使 RIP-relative LEA 也无济于事,因为它仅以 rel32
形式存在,而不是 rel8
.
单人call
,显然不值得。 如果您可以为多个 2 字节 call reg
指令重用相同的函数指针寄存器,那么即使只有 2 call
s(5 字节 mov reg, imm32
加上 2x 2 字节 call reg
总共是 9 个字节,而 2x 5 字节 call
是 10 个。但它确实要花你一个寄存器。
大多数操作系统不允许您在最低页面映射任何内容(因此 NULL-pointer deref 错误),因此可用地址大于 16 位,在 16 位模式之外。
在 32 位/64 位代码中,我认为将您的代码映射到零页所必需的链接器选项是您 code-golf 答案的 byte-count 的一部分。 (And also the /proc/sys/vm/mmap_min_addr
kernel setting,或其他操作系统上的等效项)
一般情况下,如果可以,请避免在 code-golf 中使用 call
。通常最好构建循环以避免需要 code-reuse。例如jmp
进入循环的中间,使循环的一部分达到 运行 正确的次数,而不是多次调用一个块。
我想我通常会看 code-golf 自然适合机器代码的问题,并且可以避免从多个地方需要相同的代码块。我已经可以花几个小时来调整一个简短的函数,所以开始回答一个需要更多代码的问题(因此在它的各个部分之间/之间有更多的优化空间)对我来说是很少见的。
就上下文而言,我正在打 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 个字节,即使偏移量适合一个字节!有什么办法可以用 GNU assembler 编写 call cube
和 assemble 并获得更小的偏移量吗?我知道可以使用 16 位偏移量,但理想情况下我会使用像 call reg
这样的 2 字节指令。
没有 call rel8
,也没有任何方法可以将 return 地址和 jmp
推送到少于 5 个字节。
要在 call reg
中脱颖而出,您需要在寄存器中生成一个少于 3 个字节的完整地址。即使 RIP-relative LEA 也无济于事,因为它仅以 rel32
形式存在,而不是 rel8
.
单人call
,显然不值得。 如果您可以为多个 2 字节 call reg
指令重用相同的函数指针寄存器,那么即使只有 2 call
s(5 字节 mov reg, imm32
加上 2x 2 字节 call reg
总共是 9 个字节,而 2x 5 字节 call
是 10 个。但它确实要花你一个寄存器。
大多数操作系统不允许您在最低页面映射任何内容(因此 NULL-pointer deref 错误),因此可用地址大于 16 位,在 16 位模式之外。
在 32 位/64 位代码中,我认为将您的代码映射到零页所必需的链接器选项是您 code-golf 答案的 byte-count 的一部分。 (And also the /proc/sys/vm/mmap_min_addr
kernel setting,或其他操作系统上的等效项)
一般情况下,如果可以,请避免在 code-golf 中使用 call
。通常最好构建循环以避免需要 code-reuse。例如jmp
进入循环的中间,使循环的一部分达到 运行 正确的次数,而不是多次调用一个块。
我想我通常会看 code-golf 自然适合机器代码的问题,并且可以避免从多个地方需要相同的代码块。我已经可以花几个小时来调整一个简短的函数,所以开始回答一个需要更多代码的问题(因此在它的各个部分之间/之间有更多的优化空间)对我来说是很少见的。