0

EclipseCDTとgdbを備えた64ビットリトルエンディアンUbuntu12.04LTSでgcc-4.7を使用してC++でインラインアセンブリを試してみました。私がやろうとしていることの一般的な方向性は、いくつかの難解なスタックベースのプログラミング言語用のある種のバイトコードインタープリターを作成することです。

この例では、一度に4ビットの命令を処理し(実際には、これは命令によって異なります)、ゼロ以外の命令がなくなると(0はnopになるため)、次の64ビットワードを読み取ります。 。

インラインアセンブリで関数スコープのラベルを使用するにはどうすればよいですか?

アセンブリ内のラベルはグローバルであるため、好ましくないようです。アセンブリステートメントからC++関数スコープのラベルにジャンプする方法が見つかりません。

次のコードは、私がやろうとしていることの例です(コメントに注意してください)。

  ...
  register long ip  asm("r8");
  register long buf asm("r9");
  register long op  asm("r10");
  ...
fetch:
  asm("mov (%r8), %r9");
  asm("add $8, %r8");
control:
  asm("test %r9, %r9");
  asm("jz   fetch"); // undefined reference to `fetch'
  asm("shr  $4, %r9");
  asm("mov  %r9, %r10");
  asm("and  $0xf, %r10");
  switch (op) {
  ...
  }
  goto control;
4

2 に答える 2

1

gccインラインasmドキュメントからの次のコメントに注意してください。

ラベルと言えば、ある「asm」から別の「asm」へのジャンプはサポートされていません。コンパイラのオプティマイザはこれらのジャンプについて認識していないため、最適化の方法を決定する際にそれらを考慮に入れることはできません。

asmまた、コンパイラがフラグの間に何かを挿入する可能性があるため、あるフラグに設定されたフラグが次のフラグで使用可能になることを信頼することはできません。

gcc 4.5以降では、次のことを実行できますasm goto

fetch:
  asm("mov (%r8), %r9");
  asm("add $8, %r8");
control:
  asm goto("test %r9, %r9\n\t"
           "jz  %l[fetch]" : : : : fetch);

asmの残りのすべては、読み取り/書き込み/クローバーリストでレジスタを宣言せずに直接レジスタを使用するため、完全に安全ではないことに注意してください。そのため、コンパイラは、レジスタに何か他のものを入れることを決定する可能性があります(asm宣言のある変数にもかかわらず-それらは決して使用されないので、それらは死んでいると判断するかもしれません)。したがって、これが実際に-O1以上で機能することを期待する場合は、次のように記述する必要があります。

  ...
  long ip;
  long buf;
  long op;
  ...
fetch:
  asm("mov (%1), %0" : "=r"(buf) : "r"(ip));
  asm("add $8, %0" : "=r"(ip) : "0"(ip));
control:
  asm goto("test %0, %0\n\t"
           "jz   %l[fetch]" : : "r"(buf) : : fetch);
  asm("shr  $4, %0" : "=r"(buf) : "0"(buf));
  asm("mov  %1, %0" : "=r"(op) : "r"(buf));
  asm("and  $0xf, %0" : "=r"(op) : "r"(op));

その時点で、Cコードとして記述する方がはるかに簡単です。

long *ip, buf, op;

fetch:
  do {
    buf = *op++;
control:
  } while (!buf);
  op = (buf >>= 4) & 0xf;
  switch(op) {
     :
  }  
  goto control;
于 2012-10-04T18:00:15.760 に答える
0

あなたはこれを行うことができるはずです:

fetch:
  asm("afetch: mov(%r8), %r9");
  ...
  asm("jz afetch");

または、ラベルを別の場所に配置することasm("afetch:");もできます。競合を避けるために別の名前に注意してください。それが必要かどうかは完全にはわかりませんが、必要だと思います。

于 2012-10-04T15:45:46.317 に答える