2012-05-03 3 views
1

私は以前のバージョンのLinuxをコンパイルしようとしていますが、git://github.com/ azru0512/linux-0.12.gitコンパイル '' カーネル/ blk_drv/ramdisk.c 'ながら'、私はramdisk.cで、'asm'をリロードしている間に 'CREG'クラスのレジスタを見つけることができません - memcpyインラインasm

if (CURRENT-> cmd == WRITE) { 
    (void) memcpy(addr, 
      CURRENT->buffer, 
      len); 
    } else if (CURRENT->cmd == READ) { 
    (void) memcpy(CURRENT->buffer, 
      addr, 
      len); 
    } else 
    panic("unknown ramdisk-command"); 

され、memcpyのは、

extern inline void * memcpy(void * dest,const void * src, int n) 
{ 
__asm__("cld\n\t" 
    "rep\n\t" 
    "movsb" 
    ::"c" (n),"S" (src),"D" (dest) 
    :"cx","si","di"); 
return dest; 
} 
は何以下のエラーメッセージ、

ramdisk.c:36:10: error: can't find a register in class 'CREG' while reloading 'asm' 
ramdisk.c:40:10: error: can't find a register in class 'CREG' while reloading 'asm' 
ramdisk.c:36:10: error: 'asm' operand has impossible constraints 
ramdisk.c:40:10: error: 'asm' operand has impossible constraints 

を得ました

私はmemcpy(include/string.h)のインラインasmの問題だと思うので、私はそれからclobberリストを削除しますが、運がありません。あなたは何がうまくいかないかを見つけるのを助けてくれますか?ありがとう!

+0

私がクロバーリストを削除ramdisk.cライン36-40と周辺のコード – hirschhornsalz

+0

を表示すると便利でしょう。あなたが "最適化を有効にする"ことを意味しているのかどうかはわかりませんが、私は-O [0..3]を動かさずに試してみます。インライン接頭辞を削除すると、 "memcpy"の多重定義が返されます。 – chenwj

+0

その後、ヘッダに移動します – hirschhornsalz

答えて

3

このためのGCCの構文は少し変わっています。

あなたは今、出力オペランドとしての特殊なターゲット・レジスタのそれぞれを指定する必要があります。

...("...instructions..." 
    : "=c"(n), "=S"(src), "=D"(dest) 

、その後、さらにソースオペランドとして同じレジスタとして:最後に、あなたが必要とする

: "0"(n), "1"(src), "2"(dest) 

と(「cc」が必要な場合は、条件コードに影響するかどうかはわかりません):

: "memory") 

次に、この命令を移動または削除しないでください。volatileまたは__volatile__のいずれかを使用する必要があります(テストケースで説明が削除された理由はわかりません)。

最後に、memcpyを無効にしようとするのは、もはやgccがその機能の実装方法を知っているためです。 gccの知識は​​で上書きできます。

これは(x86-64のマシン上でやや古いgccで、とにかく私のために)コンパイル:

extern inline void * memcpy(void * dest,const void * src, int n) 
{ 
    __asm__ volatile("cld\n\t" 
     "rep\n\tmovsb\n\t" 
     : "=c" (n), "=S" (src), "=D" (dest) 
     : "0" (n), "1" (src), "2" (dest) 
     : "memory", "cc"); 
    return dest; 
} 
+0

になります。あなたの返事、私は多くを学んだ。include/asm/memroy.hにマクロとして定義された別のmemcpyがあることがわかりました。 memcpyをコメントアウトした後、ramdisk.cエラーがなくなっても、include/string.hに定義されているmemcpy内のclobberリストは削除されません。 – chenwj

+0

これは私を混乱させます。なぜinclude/asm/memory.hを削除しますが、include/string.hだけを残すとエラーは消えてしまいます。インラインasmを書く上で正しい解決策は何ですか?コンパイラエラーは何も問題ないのですか? – chenwj

+0

コンパイラエラーがないとすべてがうまくいくとは限りません。それはあなたが次のレベルの問題に取り組むことを意味します。 :-)実装の詳細を深く掘り下げて調べるなら、gcc 2.x、3.x、および4.xはさまざまなので、実装については非常に具体的にする必要があります。 '/ usr/include /'以外のファイルをインクルードします(例えば '/ usr/local/include'からヘッダーを取得しているとします)。 – torek

0

&その理由はGCCのBugzillaで議論されているこの正確な問題:

Bug 43998 - inline assembler: can't set clobbering for input register

gccは入力を&出力レジスタをクローバーとして許可しません。 あなたの壊れた入力レジスタと、同じレジスタにダミー出力を行います。

unsigned int operation; 
unsigned int dummy; 
asm ("cpuid" : "=a" (dummy) : "0" (operation) :); 
関連する問題