8

我想将 64 位地址推入堆栈,如下所示,

__asm("pushq $0x1122334455667788");

但是我得到编译错误,我只能按以下方式推送,

__asm("pushq $0x11223344");

有人可以帮我理解我的错误吗?

我是组装新手,所以如果我的问题听起来很愚蠢,请原谅。

4

4 回答 4

18

x86-64 有一些有趣的怪癖,即使您熟悉 32 位 x86,这些怪癖也不明显……

  1. 大多数指令只能采用 32 位立即数,如果在 64 位上下文中使用,则将其符号扩展为 64 位。(指令编码只存储 32 位。)

    这意味着您可以使用pushq范围内的立即值0x0- 0x7fffffff(即用 0 位符号扩展的正符号 32 位值)或0xffffffff80000000- 0xffffffffffffffff)(即用 1 位符号扩展的负符号 32 位值) . 但是您不能使用超出此范围的值(因为它们无法在指令编码中表示)。

  2. mov是一种特殊情况:有一种编码采用完整的 64 位立即操作数。因此丹尼尔的回答(这可能是你最好的选择)。

  3. 如果您真的不想破坏寄存器,则可以使用多个较小值的推送。但是,推送两个 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

如何使用 rip 相对寻址

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