以下のように64ビットアドレスをスタックにプッシュしたいのですが、
__asm("pushq $0x1122334455667788");
しかし、コンパイルエラーが発生し、次の方法でしかプッシュできません。
__asm("pushq $0x11223344");
誰かが私の間違いを理解するのを手伝ってもらえますか?
私は組み立てに慣れていないので、私の質問がばかげていると思われる場合は失礼します。
x86-64にはいくつかの興味深い癖がありますが、32ビットx86に精通していても明らかではありません...
ほとんどの命令は32ビットの即値のみを取ることができ、64ビットのコンテキストで使用される場合は64ビットに符号拡張されます。(命令エンコーディングは32ビットのみを格納します。)
これは、- (つまり、0ビットで符号拡張された正の符号付き32ビット値)または- )(つまり、1ビットで符号拡張された負の符号付き32ビット値)pushq
の範囲の即時値に使用できることを意味します。 。ただし、この範囲外の値は使用できません(命令エンコーディングでは表現できないため)。0x0
0x7fffffff
0xffffffff80000000
0xffffffffffffffff
mov
は特殊なケースです。完全な64ビットのイミディエートオペランドを使用するエンコーディングがあります。したがって、ダニエルの答え(おそらくあなたの最善の策です)。
本当にレジスタを破損したくない場合は、小さい値の複数のプッシュを使用できます。ただし、2つの32ビット値をプッシュするという明らかなことは機能しません。64ビットの世界でpush
は、64ビットのオペランド(イミディエート定数の場合は上記のポイント1を条件とします)、または16ビットのオペランドで動作しますが、32ビットのオペランドでは動作しpushl %eax
ません(無効な場合でも)。したがって、実行できる最善の方法は、4つの16ビットプッシュです。
pushw $0x1122; pushw $0x3344; pushw $0x5566; pushw $0x7788
あなたの最善の策は、このようなことをすることです。
movq $0x1122334455667788, %rax
pushq %rax
%rax
適切と思われる他の64ビットレジスタと交換してください。
64ビットの即値を取得してスタックにプッシュできる単一の命令はありません。
pushq my_const(%rip)
...
my_const: .quad 1122334455667788