assembly NASM Intel 64位模式:为什么32位常量0xffffffff会导致“警告:有符号双字值超出界限”

zf2sa74q  于 2022-11-24  发布在  其他
关注(0)|答案(1)|浏览(156)

在NASM(2.14.02)中,指令add rbx, 0xffffffff导致
警告:有符号双字值超出界限[-w+数字溢出]
我知道64位模式下的算术逻辑运算只接受32位的常量,但0xffffffff仍然是32位宽。
为什么NASM发出警告,为什么它假定一个 signed 常量?它是否将32位-1符号扩展为64位-1(0xffffffffffffff),因此看到溢出?0x 7 fffffff工作时没有警告。
我能以某种方式使NASM相信这不是一个有符号常量,而是一个无符号常量吗?

j2datikz

j2datikz1#

0x 00000000 FFFFFFFF不能编码为32位符号扩展立即数,并且x86立即数在比操作数大小更窄时总是进行符号扩展。
您的理论在某种程度上是正确的,指令将指定的值添加到寄存器。无法对将0xffffffff添加到寄存器的指令进行编码,因为the only available encodings for add将立即数添加到64位寄存器是add r/m64, sign_extended_imm32add r/m64, sign_extended_imm8。只有mov的一种特殊编码(带有寄存器目标)可以使用64位立即数。
显而易见的编码(将0xffffffff填充到imm32中)实际上会将0xffffffffffffffff添加到rbx中,这不是您所请求的,而是与add rbx, -1相同
没有办法将一个值编码到32位字段中,导致0x 00000000 ffffffff被添加到rbx。Asm源使用值,而不是立即数的位模式。
你需要这样做:-

mov rcx, 0xffffffff     ; RCX = 0xFFFFFFFF = 0x00000000FFFFFFFF
add rbx, rcx

mov ecx, 0xffffffff也将以相同的方式设置RCX; NASM将为您优化为一个有效的5字节指令(使用implicit zero-extension to 64-bit when writing a 32-bit register),而不是需要一个带有64位立即数的10字节指令;请参阅another Q&A以了解有关机器码中MOV的不同形式的更多信息。

相关问题