Performance 具有多个加号的程序集跳转或跳转前执行加号(性能)
在汇编中,如果我有一个地址超过2000个标签的跳转表:Performance 具有多个加号的程序集跳转或跳转前执行加号(性能),performance,assembly,x86,micro-optimization,Performance,Assembly,X86,Micro Optimization,在汇编中,如果我有一个地址超过2000个标签的跳转表: .TABLE: DD .case0 DD .case1 DD .case2 DD .case3 DD .case4 ... ... ... DD .case2000 哪种方式更适合跳转寻址: 方式1: mov r12d, .TABLE ; r12d or any other registers mov ebx, [r13d]
.TABLE:
DD .case0
DD .case1
DD .case2
DD .case3
DD .case4
...
...
...
DD .case2000
哪种方式更适合跳转寻址:
方式1:
mov r12d, .TABLE ; r12d or any other registers
mov ebx, [r13d] ; r13d holds the id of case * 4 so we don't need to '4 * ebx'
add ebx, r12d ; ebx = address for Jumping
jmp ebx
方式2:(与方式1相同,但'addebx,r12d'
被删除并更改为'jmp[ebx+r12d]'
)
方式3:
mov ebx, [r13d] ; r13d holds the id of case * 4 so we don't need to '4 * ebx'
jmp [ebx + .TABLE]
在“方式1”中,由于额外的函数,我们有源代码大小问题,但我认为它在跳转方面比其他方式有更好的性能,因为我将有大约2000次跳转(不规则跳转(可能是从case0到case1000或…)
因此,对于跳转性能而言,在跳转量很大的源代码中,哪种方式更好?如果您可以不受影响地压缩跳转表,而不是在64位模式下使用qword指针,那么使用32位地址大小是一个不错的选择 否则,您可能需要加载16位或32位偏移量(
movzx
或mov
),并将64位代码的RIP相对LEA添加到一些64位基址(这也使其位置独立)
最少的指令并不总是一个解决方案
但在这种情况下,最少的指令也是最少的UOP。[disp32+reg]
寻址模式是有效的
如果您要考虑使用更多的指令,则将指针装入登记号为
jmp mem
仍然只有1个融合域uop,load micro融合到端口6跳转uop中。
因此,单独的mov
加载实际上会在前端花费更多的UOP
(索引寻址模式可能会取消分层;
jmp[.TABLE+ebx*4]
在发布/重命名阶段将花费2个uop,但在解码器和uop缓存中仍然只有1个uop。但出于某种原因,您似乎在内存中存储了一个字节偏移量,因此您不需要缩放索引。)方式1应该以jmp[ebx]结束
否则它将跳转到跳转表的中间。此外,如果您使用的寄存器仅在64位模式下可用,则可能需要进行64位地址计算。不要想得太多。使用第三种方法,它的指令数最少。@1201程序最少指令并不总是一个解决方案!@Ross Ridge r13d i它不是64位模式寄存器!!!!r13d的64位寄存器是r13!!!!r13d是32位寄存器,仅在64位模式下可用!!!!
mov ebx, [r13d] ; r13d holds the id of case * 4 so we don't need to '4 * ebx'
jmp [ebx + .TABLE]