なぜそれが不可能なのですか?
あなたはGASのドキュメントにリンクしていますが、それができない理由は何ですか?
回答: GAS は、ELF オブジェクト ファイルを介して操作をリンカに伝達する必要があります。このように伝達できるのは+
、および-
(-
は単なる+
負の値です) だけです。したがって、これは ELF 形式の根本的な制限であり、GAS 開発者の怠慢だけではありません。
GAS がオブジェクト ファイルにコンパイルされると、リンク ステップが続き、シンボルの最終的な値を決定するのは再配置です。
質問:+
伝えられるのに、伝えられないのはなぜ&
ですか?
回答: なぜなら+
は推移的: です(a + b) + c == a + (b + c)
が+
、 と&
は「一緒に推移的」: ではありません(a & b) + c!= a & (b + c)
。
+
ELF 形式で がどのように伝えられ、それ&
が不可能であると自分自身に納得させるかを見てみましょう。
慣れていない場合は、最初に再配置とは何かを学びます: https://stackoverflow.com/a/30507725/895245
同じエラーを生成する別の例で例を最小化しましょう。
a: .long s
b: .long s + 0x12345678
/* c: .long s & 1 */
s:
コンパイルと逆コンパイル:
as --32 -o main.o main.S
objdump -dzr main.o
出力には次が含まれます。
00000000 <a>:
0: 08 00 or %al,(%eax)
0: R_386_32 .text
2: 00 00 add %al,(%eax)
00000004 <b>:
4: 80 56 34 12 adcb $0x12,0x34(%esi)
4: R_386_32 .text
これはコードではないため、逆アセンブルは無視して、シンボル、バイト、および再配置だけを見てください。
R_386_32
引っ越しが2回あります。System V ABI for IA-32 (ELF フォーマットを定義) から、そのタイプの再配置は次のように計算されます。
S + A
どこ:
S
:オブジェクトファイルの再配置前の値。
a
再配置前の値== 08 00 00 00
==8
リトルエンディアン
b
再配置前の値== 80 56 34 12
==0x12345680
リトルエンディアン
A
: addend は、再配置エントリのフィールドです0
( では示されていませんobjdump
)。
移転が発生した場合:
a
次のものに置き換えられます。
address of text section + 8
テキスト セクションの 8 番目のバイトである+ 8
becauseがあり、その前に 2 つの long があります。s:
b
次のものに置き換えられます。
address of text section + (0x12345678 + 8)
==
address of text section + 0x12345680
ああ、それで0x12345680
オブジェクトファイルに現れたのです!
先ほど見たよう+
に、実際のオフセットに追加するだけで ELF ファイルを表現できます。
しかし&
、このメカニズム (または私が知っている他のメカニズム) で表現することはできません。なぜなら、再配置後のテキスト セクションのアドレスがどうなるかがわからないため、適用できない&
からです。