4

x86-64用のアセンブリで特別なルーチンを作成しようとしています(x86の例でも問題ありません)。問題: 私の即時はリンク時にのみ解決されます。

例えば、

addq $Label2-Label1, %rax

2 つのラベル/シンボルの違いを rax に追加します。残念ながら、GNU Assembler は 1 つのパスしか実行しないため (FASM のようなオープン ソースのアセンブラーでさえ複数のパスを実行する理由はわかりません)、それらを解決できないため、リンカーに実行させます。

残念ながら、リンカー用に 4 バイト (32 ビットの即値) が予約されますが、これは私が望んでいるものではありません。ラベルの違いは常に -128 から +127 の範囲内にあるためです。

私の質問は、命令が 8 ビットの即値を持つ必要があることを強制または指定するにはどうすればよいですか? ここの構文は何ですか?AT&T 構文または Intel では、どちらでも問題ありません。たとえば、NASM では次のようにします。

add rax, byte Label2-Label1

8bit即値を指定します。しかし、GASでこれを行う方法は? 即時自体がわからない場合でも、強制的に8ビットの即時を使用する構文は何ですか...特定の理由から、理想的にはこれをGASで使用したいので、NASMを使用するように言わないでください答え!

編集:申し訳ありませんが、言及するのを忘れていました。はい、ここでは「前方参照」です。両方のラベルは命令の後に定義されているため、GAS はそれらを解決できません。再配置だと思いましたが、「.byte label2-label1」を使用すると、テストしたので確実に機能するため、可能であることはわかっています。何らかの構文があれば...

4

2 に答える 2

4

Label1とが同じソース ファイルにある場合Label2、問題はリンカに関連しているようには見えず (この場合、GAS は再配置を生成しません)、実際には GAS がワンパス アセンブラであることが原因ではありません。同様の問題である正しいサイズのブラン​​チを生成するのに十分スマートです。

問題は、GAS がジャンプと分岐以外の場合に適切なサイズの命令を選択するほど賢くなく、オペランドのサイズを明示的に指定する方法がないことに帰着します。「.d8」ディスプレイスメントサフィックスは、ほぼ必要な構文ですが、技術的にはディスプレイスメントを使用していません。leal.d8 Label2-Label1(%eax),%eaxしかし、ディスプレイスメントが実際に使用されているにもかかわらず、動作しないため、とにかく動作しません。

つまり、オペコードを手作業で組み立てるという 1 つの選択肢しか残されていません。たとえば、32 ビット アセンブリでは次のようになります。

.byte 0x83, 0xC0, (label2 - label1)

GAS がワンパス アセンブラにすぎず、一般に他のアセンブラが多くのことを行わない理由については、答えは簡単です。主に GCC の出力をアセンブルするように設計されています。

于 2014-08-20T23:31:42.983 に答える
1

残念ながら、これは不可能です。GAS は違いが何であるかを判断できないため、リンカが解決できるように 4 バイトの再配置エントリを残すしかありません。これは、オブジェクト ファイル形式 (ELF である可能性が高い) が 8 ビットの再配置をサポートしていないためです。32 ビットの再配置しかサポートしていません。したがって、常に 32 ビットの即値が使用されます。

于 2014-08-20T21:59:01.890 に答える