【发布时间】:2018-03-07 13:18:41
【问题描述】:
这是我想做的:
add rsi, word [rsi+16]
我想读取 rsi+16 地址的无符号短值。我想将此值添加到 rsi。
这是我在 nasm 中遇到的错误:
s2.asm:62: error: mismatch in operand sizes
这很奇怪。为什么 nasm 和我的 cpu 无法将 16 位添加到 64 位寄存器?
这是我所做的工作:
mov rbx,0
mov bx, word [rsi+16]
add rsi, rbx
这很奇怪,有没有最好的方法?
谢谢
【问题讨论】:
-
指令操作数必须具有相同的大小,符号和零扩展移动指令除外。还有don't use
mov reg, 0. Always usexor reg, reg -
movzx ebx, word [rsi+16]会将字零扩展为rbx(x86_64 中写入ebx会自动清除rbx的高32 位,但指令编码比@987654331 短1 个字节@)。然后add rsi,rbx...即您的解决方法原则上是正确的,这并不奇怪,使用组合学知识来想象机器指令编码的爆炸式增长以拥有所有可能的操作数组合。类型之间的转换在代码中非常罕见(如果由了解此限制的人编写),需要额外付费。转换是最好的。 -
@TigerTV.ru 会有不正确的结果。 (OP专门要求64b添加结果)即
1 + 0xFFFF将导致为零,而不是0x10000。 -
@TigerTV.ru 是的,如果你知道你正在添加“假”64b 值,即
add的结果永远不会设置 CF,你可以使用add si,[rsi+16],但你仍然需要付费某些架构上的性能损失,当您将使用完整的rsi时,它仅由si部分更新,因此性能方面最好先使用一些备用寄存器将字值扩展为 64b,然后添加两个 64b寄存器(如果您将使用rsi)。或者,如果您只需要单词值,则仅使用si。 -
@fuz:该错误报告的要点是代码生成需要在标志设置之前执行
xor-zeroing。 IDK 为什么这对于首先创建那个错误设计的人来说并不明显;xor-zero /test/setcc有效,但test/xor-zero /setcc无效,正如 Lu'u 在他说“总是”。唯一一次你想在标志设置后使用test/setcc/movzx eax,al或使用mov eax,0是当寄存器压力让你在标志设置指令之后没有备用寄存器时。而movq与movl相比是愚蠢的。