1

以前のバージョンの Linux をコンパイルしようとしています。ソース コードは git://github.com/azru0512/linux-0.12.git からダウンロードできます。「kernel/blk_drv/ramdisk.c」のコンパイル中に、以下のエラー メッセージが表示されました。

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

ramdisk.cの内容は、

  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;
}

memcpy (include/string.h) インライン asm の問題だと思うので、そこから clobber リストを削除しますが、運が悪いです。何が問題なのかを調べるのを手伝ってもらえますか? ありがとう!

4

2 に答える 2

3

このための GCC の構文は、少し変更/進化しました。

ここで、各特殊ターゲット レジスタを出力オペランドとして指定する必要があります。

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

さらに、ソースオペランドと同じレジスタとして:

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

そして最後に、「メモリ」を上書きする必要があります(これが条件コードに影響するかどうかは覚えていません。そうであれば、「cc」も必要になります):

   : "memory")

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

memcpy最後に、 gcc は関数の実装方法を「知っている」ため、オーバーライドを試みることはもはや良い考えではありません。で gcc の知識をオーバーライドできます-fno-builtin

これはコンパイルされます(とにかく、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;
}
于 2012-05-04T06:34:35.433 に答える
0

この正確な問題とその理由は、GCC の bugzilla で議論されています:

バグ 43998 - インライン アセンブラ: 入力レジスタの上書きを設定できない

gcc は入力および出力レジスタをクロバーとして許可しません。入力レジスタを破損した場合は、同じレジスタにダミー出力を行います。

unsigned int operation;
unsigned int dummy;
asm ("cpuid" : "=a" (dummy) : "0" ( operation) :);
于 2013-01-24T20:56:24.140 に答える