以下は、2 つの Pentium アセンブリ シーケンスのリストからのクリップです。シーケンスのタイミングを計ろうとする外部ループがあり、これらのルーチンに到達するためにコールスルー テーブルを実行しています。したがって、外線通話は毎回同じ場所から行われています。2 つのシーケンスの違いは、最初のシーケンスは 2 番目のシーケンスよりも命令が 1 つ少ないことです。
2 つの Intel マシンで得られる結果は大きく異なります。
CPUID 命令は、ファミリ、モデル、およびステッピングを示します。
マシン 1: ファミリー 6、モデル 15 ステッピング 11. CPUZ が「Intel Core 2 Duo E6750」を報告
命令は統計的に同じ速度で実行されます。
マシン 2: ファミリ 15、モデル 3、ステッピング 3。CPUZ は「Intel Pentium 4」を報告します。
最初のシーケンスは、2 番目のシーケンスよりも約 8% 長くかかります。
時間の増加を説明することはできません。異なるフラグ ホールドオフ、分岐の予測、レジスタの使用に関する問題などがあってはなりません。少なくとも、それはわかりません。
1 台のマシンで最初のシーケンスの実行に時間がかかる理由を知っている人はいますか?
編集: 最初のシーケンスに「XOR PTR ereg, 0」を追加すると、Pentium 4 の 2 番目のシーケンスとタイミングが一致します。
最初のシーケンス:
00000040 ALUSHIFT_AND_C_V_E LABEL NEAR
00000040 0F B7 04 55 MOVZX EAX, gwr[(SIZEOF WORD) * EDX] ; EAX = 0000000000000000 LLLLLLLLLLLLLLLL
00000000 E
00000048 0F B7 14 4D MOVZX EDX, gwr[(SIZEOF WORD) * ECX] ; EDX = 0000000000000000 RRRRRRRRRRRRRRRR
00000000 E
00000050 23 C2 AND EAX, EDX ; AX = L&R (result)
00000052 A3 00000000 E MOV dvalue, EAX ; Save the temporary ALU/Shifter result
00000057 C3 RET ; Return
2 番目のシーケンス:
00000060 ALUSHIFT_AND_C_V_NE LABEL NEAR
00000060 0F B7 04 55 MOVZX EAX, gwr[(SIZEOF WORD) * EDX] ; EAX = 0000000000000000 LLLLLLLLLLLLLLLL
00000000 E
00000068 0F B7 14 4D MOVZX EDX, gwr[(SIZEOF WORD) * ECX] ; EDX = 0000000000000000 RRRRRRRRRRRRRRRR
00000000 E
00000070 23 C2 AND EAX, EDX ; AX = L&R (result)
00000072 80 35 00000000 E XOR BYTE PTR ereg, 1 ; E = ~E
01
00000079 A3 00000000 E MOV dvalue, EAX ; Save the temporary ALU/Shifter result
0000007E C3 RET ; Return