0

全て、

インラインアセンブリ関数でrot13を書こうとしていました...

次のコードは「a」で機能しますが、c が「z」になると機能しなくなります...

そして...常に「セグメンテーション違反」が表示されます...解決するためのアドバイスをお願いします

この問題。

#include <stdio.h>

#define add(a,b)\
asm volatile(\
    "add %%ebx,%%eax" \
    :"=a"(a) \
    :"a"(a),"b"(b) \
)

#define rot13(a)\
asm (\
"rot:\n\t"\
    "add $13,%%eax\n\t"\
    "cmpl $64,%%eax\n\t"\
    "jle L5f\n\t"\
    "cmpl $90, %%eax\n\t"\
    "jg L5f\n\t"\
    "cmpl $90,%%eax\n\t"\
    "jle L5f\n\t"\
    "subl $26,%%eax\n\t"\
"L5f:\n\t"\
    "cmpl $96,%%eax\n\t"\
    "jle L6f\n\t"\
    "cmpl $122,%%eax\n\t"\
    "jg L6f\n\t"\
    "cmpl $122,%%eax\n\t"\
    "jle L6f\n\t"\
    "subl $26,%%eax\n\t" \
"L6f:\n\t"\
    "leave\n\t"\
    :"=r"(a)\
    :"r"(a)\
)

int main()
{
    int a=13, b=12,c='z';
    rot13(c);
    printf("c-> rot13= %c\n",c);

    return 0;
}
4

1 に答える 1

3

あなたのセグメンテーション違反はleave、そこに指示があるためだと思います。インライン アセンブリは、通常の関数のようには呼び出されないため、その必要はなく、スタックが破壊されます。

もう 1 つの問題は、すべてのアセンブリが で動作するようにハードコードされているが%eax、コンパイラにそれを伝えていないことです。必要な任意のレジスタに入力を固定し、必要な他の任意のレジスタから出力を読み取ることができると考えています。常に代わりに%0andを使用することで、コードをそれに適応させることは可能ですが、入力と出力の制約を次のように変更する方がおそらく簡単です。%1%%eax

asm ( <your code here> : "=a" (a) : "0" (a) )

これは、「このインライン アセンブリの出力は である必要が%eaxあり、入力は出力と同じレジスタにある必要がある」ことを意味します。(入力制約に「a」を再度追加すると、正しく機能しなくなります。GCC のレジスタ アロケータは 28 年前からハックにハックを重ねた山であり、そのルールに従ってプレイする必要があります。ルールは " GCC マニュアルのExtended Asm " および " Constraints for Asm Operands " セクション。2 番目のセクションのすべてのサブセクションを含め、非常に注意深く読み、これは実際には内部の "マシン記述" 言語の目的を変更した機能であり、そのために最適化されています。)

これでも rot13('z') の正しい答えは得られませんが、残りの問題は、残りのプログラムとのインターフェイスではなく、rot13 アルゴリズムのバグだと思います。

于 2012-10-24T15:24:41.803 に答える