rax
1に設定するための最短の Intel x86-64 オペコードは何ですか?
私は試しxor rax,rax
てみinc al
ました(NASM構文で); これにより、5 バイトの opcode が得られます48 31 c0
fe c0
。4バイトで同じ結果を達成することは可能でしょうか?
他のレジスタを変更または読み取ることはできますが、特定の値が前の命令からそれらのいずれかにあると想定することはできません。
rax
1に設定するための最短の Intel x86-64 オペコードは何ですか?
私は試しxor rax,rax
てみinc al
ました(NASM構文で); これにより、5 バイトの opcode が得られます48 31 c0
fe c0
。4バイトで同じ結果を達成することは可能でしょうか?
他のレジスタを変更または読み取ることはできますが、特定の値が前の命令からそれらのいずれかにあると想定することはできません。
既知の前提条件があれば、push imm8/pop rax 3 バイト ソリューションよりも (速度の点で) 効率的なトリックがいくつかあります。
mov eax, 1
入力の依存関係がなく、命令が 1 つしかないため、速度には多くの利点があります。順不同の実行は、他のものを待つことなく、それ (およびそれに依存するもの) で開始できます。( Agner Fog のガイドとx86タグ wiki を参照してください)。
明らかに、これらの多くは、OP のコードの不要な REX プレフィックスを回避するために、32 ビット レジスタを書き込むと上半分がゼロになるという事実を利用しています。(また、Silvermontではゼロ化イディオムとして特殊なケースxor rax,rax
ではないことに注意してください。rax や r10 ではなく、eax や r10d などの 32 ビット レジスタの xor-ゼロ化のみを認識します。)
開始するレジスタに小さな既知の定数がある場合は、次を使用できます
lea eax, [rcx+1] ; 3 bytes: opcode + ModRM + disp8
disp8 は、-128 から +127 までの変位をエンコードできます。
eax に奇数がある場合and eax, 1
も 3 バイトです。
32 ビット コードでinc eax
は 1 バイトしか使用しませんが、これらの inc/dec オペコードは AMD64 の REX プレフィックスとして転用されました。したがって、xor eax,eax
/inc eax
は x86-64 コードでは 4 バイトですが、32 ビット コードでは 3 バイトしかありません。それでも、a に対して 1 バイトを保存するmov eax,1
だけで十分であり、LEA または AND が機能しない場合、これはプッシュ/ポップよりも効率的です。