8

以下のように64ビットアドレスをスタックにプッシュしたいのですが、

__asm("pushq $0x1122334455667788");

しかし、コンパイルエラーが発生し、次の方法でしかプッシュできません。

__asm("pushq $0x11223344");

誰かが私の間違いを理解するのを手伝ってもらえますか?

私は組み立てに慣れていないので、私の質問がばかげていると思われる場合は失礼します。

4

4 に答える 4

18

x86-64にはいくつかの興味深い癖がありますが、32ビットx86に精通していても明らかではありません...

  1. ほとんどの命令は32ビットの即値のみを取ることができ、64ビットのコンテキストで使用される場合は64ビットに符号拡張されます。(命令エンコーディングは32ビットのみを格納します。)

    これは、- (つまり、0ビットで符号拡張された正の符号付き32ビット値)または- )(つまり、1ビットで符号拡張された負の符号付き32ビット値)pushqの範囲の即時値に使用できることを意味します。 。ただし、この範囲外の値は使用できません(命令エンコーディングでは表現できないため)。0x00x7fffffff0xffffffff800000000xffffffffffffffff

  2. movは特殊なケースです。完全な64ビットのイミディエートオペランドを使用するエンコーディングがあります。したがって、ダニエルの答え(おそらくあなたの最善の策です)。

  3. 本当にレジスタを破損したくない場合は、小さい値の複数のプッシュを使用できます。ただし、2つの32ビット値をプッシュするという明らかなことは機能しません。64ビットの世界でpushは、64ビットのオペランド(イミディエート定数の場合は上記のポイント1を条件とします)、または16ビットのオペランドで動作しますが、32ビットのオペランドでは動作しpushl %eaxません(無効な場合でも)。したがって、実行できる最善の方法は、4つの16ビットプッシュです。

    pushw $0x1122; pushw $0x3344; pushw $0x5566; pushw $0x7788

于 2012-11-13T00:40:26.720 に答える
9

あなたの最善の策は、このようなことをすることです。

movq $0x1122334455667788, %rax
pushq %rax

%rax適切と思われる他の64ビットレジスタと交換してください。

于 2012-11-12T22:04:59.127 に答える
5

64ビットの即値を取得してスタックにプッシュできる単一の命令はありません。

于 2012-11-12T20:56:21.547 に答える
5

リップ相対アドレス指定の使用方法から

pushq my_const(%rip)
...
my_const: .quad 1122334455667788
于 2012-11-13T06:51:24.677 に答える