2009-09-25 10 views
10

Linuxではアセンブラを使い始めています。私はtestasm.cとして以下のコードを保存しました
コンパイルして:gcc testasm.c -otestasm
コンパイラは次のように答えます: "asmの不可能な制約"。Linuxアセンブラのエラー「asmの不可能な制約」

#include <stdio.h> 
int main(void) 
{ 
    int foo=10,bar=15; 

    __asm__ __volatile__ ("addl %%ebx,%%eax" 
     : "=eax"(foo) 
     : "eax"(foo), "ebx"(bar) 
     : "eax" 
    ); 

    printf("foo = %d", foo); 

    return 0; 
} 

この問題を解決するにはどうすればよいですか? (私はhereから例をコピーした。)

Debianのレニー、カーネル2.6.26-2-amd64の
gccのバージョン4.3.2(Debianの4.3.2-1.1)

解像度
受け入れられた回答を参照してください - それは '修正'句がもうサポートされていないようです。

答えて

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

と思われます。私は、レジスタ制約の構文がある時点で変更されたと信じていますが、それほど十分に文書化されていません。生のアセンブリを書いて面倒を避けるほうが簡単です。 1は、複数行を使用したい場合は

+0

それは、ありがとう、働いています。それはもう '変更された'節が好きではないと思われますので、変更したものをプッシュ&ポップする必要があります。 – slashmais

+2

変更された句はまだ動作します。私は問題は "出力"が暗黙的に "変更された"ことを指定していることだと思うので、両方のフィールドでeaxを表現することが問題を引き起こしていました。 –

0

、これはまた、「\」..

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

に動作します複数行の文字列(命令)を受け入れるために、コンパイラのために追加する必要があります。

+0

これはあまり良いアドバイスではありません。入力リストと出力リストで使用するレジスタを指定していますが、実際のアセンブリブロック内にハードコードされたレジスタを使用しています。代わりに '%0'と'%1'を使用してください。 –

+0

@DanielKamilKozar:受け入れられた答えはすべて1行に収まっていました。だから、同じ/類似のコードを使用して、複数行でそれを行う方法を示しました。私は、元の受け入れられた答えに使用されているハードコーディングされたレジスタを変更しようとしませんでした。なぜなら、マルチラインとシングルを比較すると分かりやすいと思ったからです。 –

5

制約は単一文字(余分な飾りが付いている可能性があります)であり、いくつかの選択肢を指定できます(つまり、中間のオペランドまたはレジスタは "ir"です)。したがって、制約 "eax"は、制約 "e"(符号付き32ビット整数定数)、 "a"(レジスタeax)、または "x"(任意のSSEレジスタ)を意味します。それはOPが意味するものとは少し違っています... "e"への出力は明らかに意味がありません。また、いくつかのオペランド(この場合は入力と出力)が別のものと同じでなければならない場合は、数値制約で参照してください。 eaxがclobberedと言う必要はなく、出力です。インラインコードの引数を%0、%1、...で参照できます。明示的なレジスタ名を使用する必要はありません。

#include <stdio.h> 

int main(void) 
{ 
    int foo=10, bar=15; 

    __asm__ __volatile__ (
     "addl %2, %0" 
     : "=a" (foo) 
     : "0" (foo), "b" (bar) 
    ); 

    printf("foo = %d", foo); 

    return 0; 
} 

より良い解決策は、%2は何もすることができるようになり、そして%0レジスタ(x86のが許す限り、しかし、あなたがする必要があるだろう。だから、OPで意図したとおりにコードの正しいバージョンは次のようになりますお使いの機械のマニュアルを参照してください):

#include <stdio.h> 

int main(void) 
{ 
    int foo=10, bar=15; 

    __asm__ __volatile__ (
     "addl %2, %0" 
     : "=r" (foo) 
     : "0" (foo), "g" (bar) 
    ); 

    printf("foo = %d", foo); 

    return 0; 
} 
関連する問題