2

私は単純ですが少し具体的なプログラムを書いています:

目的:階乗から数値を計算する
要件:すべての計算はgccインラインasmで実行する必要があります(at&t構文)

ソースコード:

#include <iostream>

int main()
{
        unsigned n = 0, f = 0;

        std::cin >> n;

        asm
        (
                "mov %0, %%eax \n"
                "mov %%eax, %%ecx \n"
                "mov 1, %%ebx \n"
                "mov 1, %%eax \n"
                "jmp cycle_start\n"
                "cycle:\n"
                "inc %%ebx\n"
                "mul %%ebx\n"
                "cycle_start:\n"
                "cmp %%ecx, %%eax\n"
                "jnz cycle\n"
                "mov %%ebx, %1 \n":

                "=r" (n):
                 "r" (f)

       );

       std::cout << f;

       return 0;
}

このコードはSIGSEVを引き起こします。

intel asm構文(http://pastebin.com/2EqJmGAV)の同一プログラムは正常に動作します。「AT&Tプログラム」が失敗するのはなぜですか。どうすれば修正できますか?

#include <iostream>

int main()
{
   unsigned n = 0, f = 0;

   std::cin >> n;

   __asm
   {
      mov eax, n

      mov ecx, eax
      mov eax, 1
      mov ebx, 1
      jmp cycle_start

      cycle:

      inc ebx
      mul ebx

      cycle_start:

      cmp eax, ecx
      jnz cycle

      mov f, ebx
   };
   std::cout << f;

   return 0;
}

UPD:スタックにプッシュして使用済みレジスタを復元すると、同じ結果が得られます:SIGSEV

4

2 に答える 2

4

あなたはあなたの入力と出力を間違った方法で持っています。

だから、変更することから始めます

            "=r" (n):
             "r" (f)

に:

             "=r" (f) :
             "r" (n)

次に、コンパイラーにクローバー(入力または出力ではない使用しているレジスター)について通知する必要があると思います。

したがって、次を追加します。

  : "eax", "ebx", "ecx" 

上記の2行の後。

私は個人的に他のいくつかの変更を行います:

  1. ローカルラベル(1:など2:)を使用します。これにより、「重複ラベル」なしでコードを複製できます。
  2. %1-の代わりに使用%%ebxします。そうすれば、余分なレジスタを使用しません。
  3. %0に直接移動し%%ecxます。後で2つの命令をロード1%%eaxているので、どのような目的で実行する必要があり%%eaxますか?

[今、私は書きすぎて、他の誰かが最初に答えました...]

編集:そして、アントンが指摘しているように$1、定数1をロードする必要があります。1つまり、アドレス1から読み取る必要がありますが、これはうまく機能せず、問題の原因である可能性があります。

于 2013-02-03T22:49:12.797 に答える
1

うまくいけば、それを理解するためにgccインラインasmだけを使用する必要はありません。AT&Tの例をnasmで翻訳してから、で逆アセンブルしてobjdump、正しい構文を確認できます。

メモリ参照ではなくリテラル定数を意味する場合は、そうあるmov 1,%eaxべきだと思います。mov $1,%eax

@MatsPeterssonによる回答は、インラインアセンブリとコンパイラの相互作用(クローバー/入力/出力レジスタ)に関して非常に役立ちます。私はあなたが得る理由に焦点を合わせましたSIGSEGV、そしてアドレスを読むこと1は質問に答えます。

于 2013-02-03T22:47:49.443 に答える