変換後のコードは、特定のアクションを実行しません[重複]

Dec 18 2020

AT&T構文に基づいて特定のコードをC ++からASMに変換するタスクが与えられたので、簡単な例から始めて、最初の問題に遭遇しました。

演習を開始したコード

void func() {
  int num = 1;
  std::cout << "before: " << num << std::endl;
  num = num << 3;
  std::cout << "after: " << num << std::endl;
}

結果が得られます:

before: 1
after: 8

私の変換変数numは最初のローカル変数なので、アドレス-4(%ebp)にある必要があります

void func() {
  int num = 1;
  std::cout << "before: " << num << std::endl;
  asm (
    "mov -4(%ebp), %eax         \n"
    "sall $3, %eax              \n"
    "mov %eax, -4(%ebp)         \n"
  );
  std::cout << "after: " << num << std::endl;
}

結果が得られます:

before: 1
after: 1

このコードがnumvarに影響を与えないのはなぜですか?

回答

2 JHBonarius Dec 18 2020 at 02:17

あなたが書いているコードは非常に実装固有です。あなたの場合、を使用ebpする64ビットマシンで実行しているときに、32ビットアドレス指定レジスタであるを使用しているため、コードが機能しない可能性がありますrbp

しかし、あなたはこれに間違ってアプローチしています。純粋なアセンブリを作成するか、ローカル変数と正しくインターフェイスする正しい(拡張された)Cインラインアセンブリを使用します。それ以外の場合は、自分で経験したように、何かを変更するとすぐにコードが壊れます。

この回答によると、インラインasmは次のようになります。

asm ( "assembly code"
    : output operands                  /* optional */
    : input operands                   /* optional */
    : list of clobbered registers      /* optional */
);

コードは次のようになります

asm (
    "mov %0, %%eax;"
    "sal $3, %%eax;"
    "mov %%eax, %1;"
    :"=r" (num)
    :"r" (num)
    :"%eax"
);

ただし、を指定して使用する必要はないeaxため、コードを次のように簡略化(および明確化)することができます。

asm (
    "sal $3, %[num];"
    :[num] "+r" (num)
);