私は自由な時間にintelアセンブリ言語(att構文)を学んでいますが、mulコマンドを使用せずに2つの数値を乗算する方法が5と2を一緒にすることができますか?x86アセンブリに2つの32ビットの数値を掛ける
答えて
あなたのCPUが何らかの形で欠陥がある場合を除き、あなたは
:-)だけ使用mul
コマンドが希望しかし、一般的な意味で、あなただけの乗算が繰り返し加えていることを認識する必要があり、そう4 x 7
は7です一緒に追加された4つの多く:4 + 4 + 4 + 4 + 4 + 4 + 4
。
ので、そのような獣のための簡単な擬似コードは次のようになります。それは符号なしの使用だと
Line# a b res
----- --- --- ---
1 5 2 ?
2 0
3 (b>0, keep going)
4 5
5 1
3 (b>0, keep going)
4 10
5 0
3 (b==0, exit loop)
6 (returns 10)
注:
def mul(unsigned a, unsigned b): # line 1
res = 0 # line 2
while b > 0: # line 3
res = res + a # line 4
b = b - 1 # line 5
return res # line 6
サンプルドライランでテストデータを使用しては、これがどのように機能するかを示し値を変更するだけで、符号付きの値を扱うことができます。
def mul(int a, int b):
sign = 1
if a < 0:
a = -a
sign = -sign
if b < 0:
b = -b
sign = -sign
res = 0
while a > 0:
res = res + b
a = a - 1
if sign == -1:
res = -res
return res
また、ビット(必要に応じて追加を最小限に抑える)値のシフトではなく、単純な繰り返し添加を含む乗算を行うための、実際に、より効率的な方法があることを心に留めておきます。そのことによって
私は9999 x 9999
のような計算が約10,000追加は簡単な方法を使用して行う必要がありますを意味します。シフトを使用すると、必要な追加を、数字の1つに9桁、他の数字の1桁に1つだけ制限することができます。つまり、上記の計算で約40個の追加を取り除くことができます。
9999 x 9 -> nine additions
+ 99990 x 9 -> nine additions
+ 999900 x 9 -> nine additions
+ 9999000 x 9 -> nine additions
\____________/
|
V
three additions
あなたは、より詳細に作品をシフトする方法を確認したい場合は、ウィキペディアはarticle on the topicを持っている:あなたは9999 x 9999
まで簡素化することができますことを認識したときに
この
は、うまくいけば意味をなさないだろう。実行する必要がある操作を事前に知っているため、定数を乗算するとかなり良いパフォーマンスが得られます。例えば、10でレジスタを掛けることは何か(私の組立日数が過去に長く、念頭に置いて)等を行うことができます。
mul_ax_by_10: push bx ; save registers
shl ax ; ax <- orig_ax * 2
push ax ; save for later add
shl ax
shl ax ; ax <- orig_ax * 8
pop bx ; bx <- orig_ax * 2
add ax, bx ; ax <- (orig_ax * 8) + (orig_ax * 2)
; <- orig_ax * (8 + 2)
; <- orig_ax * 10
pop bx ; restore saved register
ret ; result in ax
あなたはcで質問をタグ付けされているので、私はあなたが苦労していると仮定しますGCCのインラインアセンブラ。あなたは掛け算をした古き良き小数点日で
- 例えば - 11 * 14は以下のように:
をあなたは乗数(11)= 1の右端の桁を取って、被乗数とそれを掛け(14)は
14あなたは次の桁を左に取っ=乗数= 1で、被乗数= 14でそれを乗算します。また、結果の代わりに被乗数をシフトすることができます= 140一桁左に結果の小数シフト:1 * 140 = 140。このアルゴリズムは、binarismの勇敢な新しい世界でも有効です= 154 14 + 140
:
は、右端を取る
あなたが最終的な結果に結果を追加しましたビットを乗算器(1011b)の右に移動することによって乗算器(1011b)を乗算する。これを被乗数(1110b)で「乗算」する。これは実際に乗算ではありません。 0 * 1110b = 0と1 * 1110b = 1110bという2つのオプションしかありません。結果はビット0または被乗数に従います。それを最終結果に加えます。
乗数がヌルより大きい場合、次のビットは乗数の右端のビットとして待機します。 1ビットだけ左に被乗数(上記ステップ2の第二のオプション)とGotoステップをシフト1.
GCCプログラム:
#include <stdio.h>
unsigned mul (unsigned multiplier, unsigned multiplicand)
{
unsigned r = 0;
while (multiplier)
{
if (multiplier & 1) r += multiplicand;
multiplier >>= 1;
multiplicand <<= 1;
}
return r;
}
unsigned mul_asm (unsigned multiplier, unsigned multiplicand)
{
unsigned result = 0;
asm
(
"movl %[multiplier], %%edx;" // EDX = multiplier
"movl %[multiplicand], %%ecx;" // ECX = multiplicand
"xorl %%eax, %%eax;" // Result = 0
"L1:;" // While-loop
"shrl $1, %%edx;" // Get rightmost bit of the multiplier
"jnc 1f;" // Skip the next line if this bit == 0
"leal (%%ecx,%%eax), %%eax;" // Add multiplicand to result (without changing flags)
"1:;" // Local jump label
"leal (,%%ecx,2), %%ecx;" // Shift multiplicand left by one bit (without changing flags)
"jnz L1;" // While EDX != 0 (zero flag from the shrl-line)
"movl %%eax, %[result];" // Return value
: [result] "=m" (result) // Output
: [multiplier] "m" (multiplier), // Input
[multiplicand] "m" (multiplicand)
: "%eax", "%ecx", "%edx", "cc" // Clobbered registers & flags
);
return result;
}
int main (void)
{
unsigned result, multiplier, multiplicand;
multiplier = 17;
multiplicand = 23;
result = multiplier * multiplicand;
printf ("direct: %u * %u = %u\n", multiplier, multiplicand, result);
result = mul (multiplier,multiplicand);
printf ("mul: %u * %u = %u\n", multiplier, multiplicand, result);
result = mul_asm (multiplier,multiplicand);
printf ("mul_asm: %u * %u = %u\n", multiplier, multiplicand, result);
return 0;
}
- 1. 32ビットアーキテクチャ上で2つの10桁の32ビットの数値を掛ける
- 2. アセンブラi8080 2つの16ビット数を掛け合わせる
- 3. アセンブリ内に2つの64ビット数値を追加する
- 4. 2つの値を掛ける
- 5. Linuxの32ビットx86でのバッファオーバーフロークエリ
- 6. C++の32ビット数に2つの数値を格納する方法
- 7. x86:32ビットの数値で1から0への遷移をカウントする
- 8. Javaで2つの数値を正確に掛ける
- 9. x86アセンブリ内のメモリに64ビット定数を移動する
- 10. 64ビットの数値から2の32ビット
- 11. 32ビット乗算アセンブリiApx88
- 12. 255より大きい2つの数値を掛ける
- 13. 2つの数値を掛けるMIPSプログラム
- 14. Sparc 32ビットの値が2^32を超える整数の処理
- 15. 32ビットの数値を16ビット以下に変換する
- 16. 32ビット用の64ビットplaformでアセンブリをコンパイルする
- 17. RedmineをWindows 32ビット(x86)にインストールするためのステップバイステップガイド
- 18. x86アセンブリでmulと即座に掛けることはできますか?
- 19. x86アセンブリ言語上位と下位ビット
- 20. x86アセンブリ関数
- 21. は32ビット整数1つの方法の第31ビット(MSB)を読み出すために32ビット整数
- 22. 2つの32ビットレジスタを持つx86 imulオペコード
- 23. アセンブリでのマルチスレッド32ビットまたは16ビット
- 24. $ {env:ProgramFiles(x86)} Powershell変数には32ビット/ x86システムに含まれるものは何ですか?
- 25. リセット後にx86 "32ビット"のソフトリセットが解除されますか?
- 26. メモリエラー:2つの行列を掛ける
- 27. 2つの行列を掛けるR
- 28. Erlang:2つのリストを掛ける
- 29. Python:2つのリストを掛ける
- 30. アセンブリのx86上の文字列を分割する16ビット
あなたが2の倍数を有するので、あなたは左シフトを使用することができます/ 2倍または2の倍数で複数倍/右にシフトすることができます。 – dawg
こんにちはジャック、あなたはASMで答えが必要な場合は、[アセンブリタグ](http://stackoverflow.com/questions/tagged/assembly)ではなく、[cタグ](http://stackoverflow.com/questions/tagged/c)... – Myst
あなたは 'imul'を使うこともできます。または「ああ」。 – fuz