【发布时间】:2021-12-03 10:35:19
【问题描述】:
假设我们有以下一段汇编代码:
mulx const, %rax, %r11
其中 const 是硬编码常数,已知是 2 的幂(让我们假设它是 2^24)。
根据https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/ia-large-integer-arithmetic-paper.pdf第8页:
mulx指令是现有mul指令的扩展,具有 不同之处在于对标志的影响:mulx dest_hi, dest_lo, src1该指令还使用隐式 src2 寄存器,
edx或rdx,具体取决于 使用的是 32 位还是 64 位版本。
操作是:dest_hi:dest_lo = src1 * r/edx
转换为 GAS 语法(另请参见 What is the AT&T / GAS syntax for mulx?)我们应该有:
%r11:%rax = const * %rdx
在我们的例子中,我们希望找到一段不涉及乘法(并且不修改标志)的等效代码。我们可以这样写:
movq %rdx, %r11
movq %rdx, %rax
shl $24, %rax
shr $40, %r11
但这是修改进位标志。我还尝试了其他一些移位指令的变体(不修改标志),但它们给出了错误。
我的电脑配备 Intel Core i7 处理器。
【问题讨论】:
-
应该是等价的;你确定你的
mulx源操作数的值是正确的吗?如果你真的写了myconst: .quad 2^24,你会得到一个汇编时的异或运算,而不是求幂。这些指令都没有读取 CF,但是如果您考虑输出,它们当然会对 CF 产生不同的影响。 (班次设置 CF,mulx保留所有 FLAGS 未修改。) -
彼得所说的。请提供minimal reproducible example 和预期与实际输出。
-
@PeterCordes,谢谢。其实情况是这样的:我用的是宏llvm_asm!锈。我不希望更改进位标志(因此我们可以说我将它们视为输出)。我看到应该使用移位命令 shlx/salx 和 shrx/sarx,以避免进位标志更新。然而,看起来他们不被认可。错误消息是“指令操作数无效”。
-
您应该编辑您的问题,以便更清楚地了解 CF 是您关心的输出,这是输出的唯一区别。一般来说,这是非常不寻常的。大多数 x86 指令都基于标志。 (并且 GNU C 内联 asm 对 i386 和 x86-64 目标有一个隐含的“cc”clobber;如果 Rust 内联 asm 可能不同,则为 IDK。)不幸的是,根据 ISA 参考 @987654324,SHLX/SHRX 仅适用于寄存器源@。唯一需要立即进行的无标志移位实际上是轮换,BMI2 RORX。
-
可能没用的想法:
lea让您移动 1、2 或 3。rorx $56, %rax, %rax ; mov $0, %al移动 8。rorx $48, %rax, %rax ; mov $0, %ax移动 16。
标签: assembly x86 inline-assembly att