s0128符号付き整数型、s0256、s0512、s1024および浮動小数点型f0128、f0256、f0512のすべての従来の演算子と関数を提供する関数ライブラリを作成していますf1024。
s0128, s0256, s0512,乗算ルーチンを書いてs1024いますが、間違った結果が得られて混乱しています。命令で符号なしオペランドを使用して同じことを行うことができるのと同じ方法で、64 ビットimul rcx命令 (で 128 ビットの結果を生成する) で乗算をカスケードできると仮定しましたが、 の答えは間違っています。rdx:raxmul rcximul
imulこれを機能させるには、おそらくミックスとmul指示など、いくつかのトリックがあると思います。それとも、符号付き乗算命令でより大きな乗算を実装できない理由がありますか?
テクニックを理解したので、s0128オペランドの最小バージョンについて説明します。
arg2.1 arg2.0 : two 64-bit parts of s0128 operand
arg1.1 arg1.0 : two 64-bit parts of s0128 operand
---------------
0 out.edx out.eax : output of arg1.0 * arg2.0
out.edx out.eax : output of arg1.0 * arg2.1
-------------------------
out.2 out.1 out.0 : sum the above intermediate results
out.edx out.eax : output of arg1.1 * arg2.0
-------------------------
out.2 out.1 out.0 : sum the above intermediate results
コードが 2 つの 64 ビット値を乗算するたびに、128 ビットの結果が に生成されedx:eaxます。コードが 128 ビットの結果を生成するたびに、その結果をaddq, adcq,adcq命令で 64 ビット レジスタの累積トリプルに加算します (ここで、最後のadcq命令はキャリー フラグが伝搬されることを保証するためにゼロを追加するだけです)。
テストとして小さな負の数を小さな正の数で乗算すると、結果は負になりますが、128 ビットの結果の上位 64 ビット値の下部にゼロ以外のビットが 1 つまたは 2 つありますs0128。これは、多倍精度の符号付き乗算の伝播で何かが正しくないことを意味します。
s0256もちろん、カスケードは、s0512、の場合はかなり広範囲ですs1024。
私は何が欠けていますか?両方のオペランドを符号なしに変換し、符号なし乗算を実行してから、オペランドの一方 (両方ではない) が負の場合、結果を否定する必要がありますか? imulまたは、符号付き乗算命令を使用して多倍精度の結果を計算できますか?