Assembly 我可以在x86中编码64位负立即数吗?

Assembly 我可以在x86中编码64位负立即数吗?,assembly,x86,32bit-64bit,twos-complement,integer-arithmetic,Assembly,X86,32bit 64bit,Twos Complement,Integer Arithmetic,我试图自学x86,我遇到了立即返回负数的需要: .text .align 4,0x90 .globl _scheme_entry _scheme_entry: movl $-42, %eax ret 当我打印此函数的返回值(printf(“%”PRIdPTR“\n”,scheme\u entry())时,我得到一个无意义的数字: $ ./neg 4294967254 我猜这是因为它是32位负数,

我试图自学x86,我遇到了立即返回负数的需要:

.text
.align 4,0x90
.globl _scheme_entry
_scheme_entry:
movl $-42, %eax
ret
当我打印此函数的返回值(
printf(“%”PRIdPTR“\n”,scheme\u entry())
时,我得到一个无意义的数字:

$ ./neg                                                 
4294967254
我猜这是因为它是32位负数,00000000FFFFFFFF,而不是64位负数,ffffffffffff


如何将恒定的64位值直接存储在汇编函数中?是否必须将其编码为两条单独的指令?

32位指令的32位立即数(如
movl
)按原样使用,并且。您不会得到无意义的结果,您得到的是
2^32-42
,这正是您应该期望的,因为x86使用2的补码有符号整数

具有64位操作数大小的指令的32位直接指令被符号扩展为64位

使用
mov$-42,%rax
返回负64位值,而不是略低于2^32的正64位值。(使用
%rax
作为目标意味着64位操作数大小,即
movq


使用调试器查看寄存器中的值。

32位指令的32位立即数(如
movl
)按原样使用,并且。您不会得到无意义的结果,您得到的是
2^32-42
,这正是您应该期望的,因为x86使用2的补码有符号整数

具有64位操作数大小的指令的32位直接指令被符号扩展为64位

使用
mov$-42,%rax
返回负64位值,而不是略低于2^32的正64位值。(使用
%rax
作为目标意味着64位操作数大小,即
movq


使用调试器查看寄存器中的值。

您打印的不是错误吗?
scheme\u条目
似乎返回32位整数(如果不是,那么为什么要将其放入
eax
?)gcc通常将函数入口点对齐到16个字节。也没有理由强制填充为单字节NOP(因为它永远不会运行)。使用
.p2align 4
对齐到
1@PeterCordes这其中有相当一部分超出了我的理解力——我正在跟进,这是有意让我们使用
gcc
的输出作为微小的C输入,以决定从我们的编译器中发出什么。上面的样板文件基本上是逐字复制的,但我还不知道它的作用是什么!:xI don“不知道您是否可以使用编译器/语言(80686+)访问64位寄存器(如RAX寄存器);如果是真的,您可以编写MOV$-42,%RAX;函数结果必须是64位类型。您打印的结果是否错误?
scheme\u entry
似乎返回32位整数(如果不是,那么为什么要将其放入
eax
?)gcc通常将函数入口点对齐到16字节。也没有理由强制填充为单字节NOP(因为它永远不会运行)。使用
.p2align 4
对齐到
1@PeterCordes这其中有相当一部分超出了我的理解力——我正在跟进,这是有意让我们使用
gcc
的输出作为微小的C输入,以决定从我们的编译器中发出什么。上面的样板文件基本上是逐字复制的,但我还不知道它的作用是什么!:xI don“我不知道您是否可以使用编译器/语言(80686+)访问64位寄存器(如RAX寄存器);如果是真的,您可以编写MOV$-42,%RAX;函数结果无论如何都必须是64位类型。这是非常好的信息!是的,我知道2的补码;但是
%RAX
(和
mov
vs
movl
,显然?)是我在这里丢失的片段。我会用这个来运行!谢谢!@ELLIOTTCABLE,而不是它的movl vs movq。如果从操作数中看清楚后缀,可以省略。这是非常好的信息!是的,我知道两个的补码;但是
%rax
(显然,
mov
vs
movl
)是我在这里丢失的部分。我将用这个来运行!谢谢!@ELLIOTTCABLE,而不是它的movl vs movq。如果操作数中没有后缀,可以省略后缀。