Pet*_*des 7 x86 assembly nasm machine-code micro-optimization
为了有效地做x = x*10 + 1,它可能是最佳使用
lea eax, [rax + rax*4] ; x*=5
lea eax, [1 + rax*2] ; x = x*2 + 1
Run Code Online (Sandbox Code Playgroud)
3组件LEA在现代Intel CPU上具有更高的延迟,例如3个周期而不是Sandybridge系列的1个,因此disp32 + index*2比disp8 + base + index*1SnB系列更快,即我们关心优化的大多数主流x86 CPU.(这主要仅适用于LEA,而不适用于加载/存储,因为LEA运行在ALU执行单元上,而不是大多数现代x86 CPU中的AGU.)AMD CPU具有3个组件的LEA较慢或scale > 1(http://agner.org/optimize /)
但NASM和YASM将通过使用[1 + rax + rax*1]第二个LEA 来优化代码大小,第二个LEA只需要disp8而不是disp32.(寻址模式始终具有基址寄存器或disp32).
即他们总是分裂reg*2成base+index,因为对于代码大小来说,这永远不会更糟.
我可以强制使用disp32 lea eax, [dword 1 + rax*2],但这并不能阻止NASM或YASM分割寻址模式.在NASM手动似乎并没有记录的方式来使用的strict关键字上规模的因素,并[1 + strict rax*2]没有装配. 有没有办法使用strict或其他语法来强制寻址模式的所需编码?
nasm -O0禁用优化不起作用.显然,只控制多次通过分支位移优化,而不是NASM所做的所有优化.当然,您不希望首先对整个源文件执行此操作,即使它确实有效.我还是得到的
8d 84 00 01 00 00 00 lea eax,[rax+rax*1+0x1]
Run Code Online (Sandbox Code Playgroud)
我能想到的唯一解决方法是手动编码db.这非常不方便.为了记录,手动编码是:
db 0x8d, 0x04, 0x45 ; opcode, modrm, SIB for lea eax, [disp32 + rax*2]
dd 1 ; disp32
Run Code Online (Sandbox Code Playgroud)
比例因子编码在SIB字节的高2位中.我组装lea eax, [dword 1 + rax*4]了正确的寄存器的机器代码,因为NASM的优化仅适用于*2.SIB是0x85,并且递减字节顶部的2比特字段将比例因子从4减少到2.
但问题是:如何以一种易读的方式编写它,以便更改寄存器,并让NASM为您编码寻址模式? (我想一个巨大的宏可以用文本处理和手动db编码来做到这一点,但这并不是我正在寻找的答案.我现在实际上并不需要这个,我主要想知道NASM或YASM是否有强制执行此操作的语法.)
其他优化我知道的,就像mov rax, 1组装到5个字节的mov eax,1是,除非你想长指令来获取填充不NOP指令所有CPU纯净胜,并且可以禁用与mov rax, strict dword 1获得7字节的符号扩展编码,或strict qword10 -byte imm64.
gas不会执行此操作或进行大多数其他优化(仅限immediates和分支位移的大小): lea 1(,%rax,2), %eax汇编到版本
8d 04 45 01 00 00 00 lea eax,[rax*2+0x1],并且.intel_syntax noprefix版本相同.
但是MASM或其他汇编程序的答案也会很有趣.
同样,NASM将分裂
[eax*2]成[eax+eax]因为它允许偏移字段不存在并节省空间; 事实上,它也会分裂[eax*2+offset]成[eax+eax+offset].
您可以通过使用NOSPLIT关键字来解决此问题:[nosplit eax*2]将强制[eax*2+0]生成字面意思.
[nosplit eax*1]也有同样的效果.换句话说,[0, eax*2]也可以使用拆分EA表单.然而,NOSPLIT在[nosplit eax+eax]因为这里用户的意图被认为是会被忽略[eax+eax].
lea eax, [NOSPLIT 1+rax*2]
lea eax, [1+rax*2]
00000000 8D044501000000 lea eax,[rax*2+0x1]
00000007 8D440001 lea eax,[rax+rax+0x1]
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
248 次 |
| 最近记录: |