x86-64 AT&T语法下不破坏操作数的三操作数ADD汇编失败原因问询
问题解答
核心错误原因
- 你误解了英特尔手册的表述:VEX编码支持三操作数语法的仅为VEX编码的新增指令(如SIMD向量指令、BMI/BMI2扩展位操作指令等),传统通用整数
add指令无论使用什么前缀、什么架构,硬件层面都只有两操作数的编码,根本不存在三操作数的整数add指令,GNU汇编器自然无法识别。 - 即使是支持三操作数的VEX指令,你的AT&T语法使用也不符合规范:AT&T语法统一遵循「源操作数在前、目的操作数在后」的规则,三操作数指令的最后一个操作数才是目的寄存器,和你预期的操作数赋值逻辑也不匹配。
你传递-march=skylake参数无效的原因也很简单:即使是Skylake架构支持的BMI1、BMI2扩展集中,也没有新增三操作数的通用整数加法指令。
替代实现方案
如果你想单指令完成c = a + b且不修改原a、b的值,不需要依赖不存在的三操作数add,直接使用x86-64原生支持的LEA指令即可:
asm volatile ( "lea (%[a], %[b]), %[c]\n\t" : [c] "=&r" (c) : [a] "r" (a), [b] "r" (b) : /* 不需要标记cc,因为lea不影响标志位 */ );
该指令可以直接将两个寄存器的和写入目标寄存器,不需要额外的mov操作,也不会修改标志寄存器,所有x86-64平台都可正常运行。
内容的提问来源于stack exchange,提问作者thb
相关产品推荐
相关产品推荐

