我想将 64 位地址推入堆栈,如下所示,
__asm("pushq $0x1122334455667788");
但是我得到编译错误,我只能按以下方式推送,
__asm("pushq $0x11223344");
有人可以帮我理解我的错误吗?
我是组装新手,所以如果我的问题听起来很愚蠢,请原谅。
x86-64 有一些有趣的怪癖,即使您熟悉 32 位 x86,这些怪癖也不明显……
大多数指令只能采用 32 位立即数,如果在 64 位上下文中使用,则将其符号扩展为 64 位。(指令编码只存储 32 位。)
这意味着您可以使用pushq
范围内的立即值0x0
- 0x7fffffff
(即用 0 位符号扩展的正符号 32 位值)或0xffffffff80000000
- 0xffffffffffffffff
)(即用 1 位符号扩展的负符号 32 位值) . 但是您不能使用超出此范围的值(因为它们无法在指令编码中表示)。
mov
是一种特殊情况:有一种编码采用完整的 64 位立即操作数。因此丹尼尔的回答(这可能是你最好的选择)。
如果您真的不想破坏寄存器,则可以使用多个较小值的推送。但是,推送两个 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