x86-64 AT&T汇编:单指令实现16位内存数与寄存器相乘存32位?
问题分析与解答
你的需求是在x86-64 AT&T汇编中,用单条指令完成「内存中16位无符号数 × %ax中的16位无符号数」,并将完整32位结果存入%eax且不截断。
结论
不存在完全匹配需求的单条x86指令,但可根据场景选择两种可行方案:
方案1:单操作数乘法+结果合并(无符号安全)
单操作数mulw指令会将16位乘法的完整32位结果存在%dx:%ax寄存器对中,后续通过少量指令即可合并到%eax:
mulw (num) # %ax × num → 低16位存%ax,高16位存%dx movzwl %ax, %eax # 低16位零扩展到%eax shll $16, %edx # 高16位移到%edx的高半部分 orl %edx, %eax # 合并完整32位结果到%eax
这是无符号乘法的标准实现,完全适配你的数据场景,仅需额外3条指令。
方案2:符号扩展乘法(限乘积≤2^31-1的场景)
如果能保证乘积不超过31位(即≤2^31-1,小于有符号32位最大值),可直接用imulw指令:
imulw (num), %eax # %ax × num(有符号乘法),结果符号扩展为32位存入%eax
由于你的操作数均为非负(%rax是零扩展的16位值,num是无符号最大值),当乘积≤231-1时,有符号乘法结果与无符号乘法完全一致,这条指令可直接得到正确的32位结果。但如果乘积可能达到232-1,该指令会因有符号溢出返回错误的负数结果,不可使用。
为什么没有单条指令?
x86指令集的设计限制了这一点:
- 16位单操作数乘法(
mulw/imulw)的结果固定存在%dx:%ax寄存器对,无法直接存入单个32位寄存器; - 双操作数乘法指令(如
imulw src, %ax)仅保留与操作数宽度一致的结果(截断到16位),无法输出32位结果; imull指令要求内存操作数为32位,会错误读取num后面的junk数据,不能用于16位内存值的乘法。
内容的提问来源于stack exchange,提问作者Shay
相关产品推荐
相关产品推荐

