mov&jmp to&jmp back vs call&ret

问题描述 投票:1回答:1

我正在查看一些汇编代码,我看到了这个:

    mov r12, _read_loopr
    jmp _bzero
_read_loopr:
...
_bzero:
    inc r8
    mov byte [r8+r15], 0x0
    cmp r8, 0xff
    jle _bzero
    jmp r12

而且我想知道这样做是否有任何特别的优势(mov _read_loopr到函数寄存器jmp然后jmp返回)而不是通常的调用_bzero和ret?

assembly x86-64
1个回答
3
投票

这看起来就像是脑死亡代码,特别是如果返回地址标签总是在jmp _bzero之后,就像你在评论中说的那样。

也许作者认为他们不能使用call“因为函数调用clobber寄存器”。如果您正在调用不属于同一代码库的函数,则必须根据调用约定进行假设。但是你可以使用call / ret来实现自定义调用约定。

当然,对于这么小的代码,应该内联(即使其成为宏,而不是函数)。

更重要的是,通常可以比一次存储一个字节更聪明,并且如果有多个字节为零,则可能值得潜在的分支误预测。如果始终需要将至少8个(或更好,16个)字节的数据归零,则可以使用宽存储执行此操作。使最终存储写入要归零的缓冲区的最后一个字节,可能与前一个存储重叠。 (这比以分支机构结束决定进行最终4B商店,2B商店和1B商店要好得多。)有关编写高效asm的资源,请参阅标签wiki。


如果返回地址在jmp _bzero之后的某个地方,那么最糟糕的可能是push _read_loopr / jmp _bzeroret中的_bzero。这将破坏return-address predictor stack,导致对呼叫树上的下一个~15 rets的误预测。

最好是内联循环并在其后放置直接jmp

我不确定如何将_bzero的地址传递给jmp,以便在call之后与ret / jmpcall进行比较。

call / ret相当便宜,但不是针对英特尔的单指令。如果只有一个来电者,jmp _bzero / jmp _read_loopr会更好。

© www.soinside.com 2019 - 2024. All rights reserved.