2017-02-16 44 views
0

はプログラム次の点を考慮乗算命令エラー

#include <stdio.h> 
int main(void) { 
     int foo = 10, bar = 15; 
     __asm__ __volatile__("add %%ebx,%%eax" 
          :"=a"(foo) 
          :"a"(foo), "b"(bar) 
          ); 
     printf("foo+bar=%d\n", foo); 
} 

私はadd命令を付加するために使用され、sub命令がそのように&を減算するために使用されていることを知っています。

__asm__ __volatile__("add %%ebx,%%eax" 
          :"=a"(foo) 
          :"a"(foo), "b"(bar) 
          ); 

:"=a"(foo) :"a"(foo), "b"(bar));の正確な意味は何ですか:しかし、私はこれらの行を理解していませんでしたか?それは何ですか?そして、私はここにmul命令を使用しようとすると、私は次のプログラムのエラーを以下の取得:

#include <stdio.h> 
int main(void) { 
     int foo = 10, bar = 15; 
     __asm__ __volatile__("mul %%ebx,%%eax" 
          :"=a"(foo) 
          :"a"(foo), "b"(bar) 
          ); 
     printf("foo*bar=%d\n", foo); 
} 

エラー:だから「MUL `のオペランドの不一致の数

、なぜ私はこのエラーを取得していますか?このエラーを解決するにはどうすればよいですか?私はこれらについてgoogleで検索しましたが、私の問題の解決策を見つけることができませんでした。私はWindows 10 OSを使用しています&プロセッサは、Intel Core i3です。

答えて

4

What is the exact meaning of :"=a"(foo) :"a"(foo), "b"(bar));

パラメータはASM命令hereに渡される方法の詳細な説明があります。つまり、barがebxレジスタに入り、fooがeaxに入り、asmが実行された後、eaxにはfooの更新値が含まれます。

Error: number of operands mismatch for `mul'

ええ、それはmulのための右の構文ではありません。おそらく、あなたはx86アセンブラリファレンスマニュアル(例えば、this)で時間を費やすべきでしょう。

また、インラインasmを使用すると、普通はbad ideaとなります。


編集:あなたの質問への回答をコメントに入力できません。

どこから始めたらいいかわかりません。これらの質問は、アセンブラがどのように動作するかを非常によく理解していないことを示しているようです。あなたのSOの答えをあなたに教えることを試みることは、実際には実用的ではありません。

しかし、私は正しい方向にあなたを指すことができます。

まず、ASMコードのこのビットを考慮してください。

movl $10, %eax 
movl $15, %ebx 
addl %ebx, %eax 

あなたはそれが何をするのか理解していますか?これが完了したら、eaxには何が入りますか? ebxには何がありますか?さて、これでその比較:

int foo = 10, bar = 15; 
__asm__ __volatile__("add %%ebx,%%eax" 
        :"=a"(foo) 
        :"a"(foo), "b"(bar) 
        ); 

を「」制約を使用することで、EAXにfooの値を移動するためのgccを求めています。 "b"制約を使用すると、barをebxに移動するよう求められます。これで、asm(つまりadd)の命令が実行されます。 asmを終了すると、fooの新しい値はeaxになります。それを得る?

今、mulを見てみましょう。リンク先のドキュメントによれば、構文はmul valueであることがわかりました。それは不思議そうですね。 mulにはどのように1つのパラメータしかありませんか?それはの倍数ですか?

読書を続けている場合、「EAXには常に値を乗算します」と表示されます。ああ。したがって、ここでは "eax"レジスタが常に暗黙指定されています。したがって、mul %ebxと書くと、それは実際にはmul ebx, eaxの意味になりますが、常ににはがあるので、それを書くのは実際のところありません。

しかし、それよりも少し複雑です。 ebxは32ビットの数値を保持できます。私たちはint(unsigned intsではなく)を使用しているので、ebxは2,147,483,647という大きな数値を持つことができます。しかし、あなたが2,147,483,647 * 10を掛け合わせるとどうなりますか?さて、2,147,483,647は登録簿に登録できるほど大きな数字であるため、結果は大きすぎてeaxに収まりません。したがって、乗算(常に)は2つのレジスタを使用してmulの結果を出力します。これは、そのリンクが「EDX:EAXの結果を格納する」という言い回しを意味していました。

だから、あなたはこのようなあなたの乗算を書くことができます:

int foo = 10, bar = 15; 
int upper; 
__asm__ ("mul %%ebx" 
     :"=a"(foo), "=d"(upper) 
     :"a"(foo), "b"(bar) 
     :"cc" 
     ); 

を前と同じように、これは、乗算命令を実行し、EAX、EBXにし、FOOにバーを置きます。

asmが実行された後、eaxは結果の下位部分を含み、edxは上限を含みます。 foo * bar < 2,147,483,647の場合、fooには必要な結果が含まれ、upperはゼロになります。さもなければ、事はより複雑になる。

しかし、それは私が喜んで行っている限りです。それ以外は、asmクラスを取る。本を読む。

PS this答えと、「追加」の例でも「間違っている」という理由を示す3つのコメントがあります。

PPSこの回答があなたの質問を解決した場合は、その隣にあるチェックマークをクリックして、カルマポイントを取得することを忘れないようにしてください。

+0

"a"と "b"はここで何を表していますか? – Destructor

+0

私がasmにリンクしているドキュメントを読んだ場合、引用された文字列は、asmが理解できるものにC言語変数をマップする方法を記述する「制約」であることがわかります(i386セクション[here](https:// gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html))。 "a"はeaxレジスタを指します。 「b」はebxを指します。 –

+0

ありがとうございます。わかった。しかし、私はまだ1つの問題があります。私はfooとbar変数の値を掛けて、結果をfooに格納したい。私はあなたに与えられたリンクを訪問しましたが、これを達成するために何をすべきかを知るのは難しい時があります。 – Destructor