[英]How do I negate a 64-bit integer stored in a 32-bit register pair?
我在EDX:EAX
寄存器对中存储了一个64 位整数。 我怎样才能正确否定这个数字?
例如: 123456789123
→ -123456789123
。
向编译器int64_t neg(int64_t a) { return -a; }
意见: compile int64_t neg(int64_t a) { return -a; }
int64_t neg(int64_t a) { return -a; }
在 32 位模式下。 当然,询问编译器的不同方式将在内存中、在编译器选择的寄存器中或已经在 EDX:EAX 中具有起始值。 在 Godbolt 编译器资源管理器上查看所有三种方式,以及来自 gcc、clang 和 MSVC(又名 CL)的 asm 输出。
当然有很多方法可以实现这一点,但任何可能的序列在某个时候都需要某种从低到高的进位,因此没有有效的方法来避免 SBB 或 ADC。
如果该值在 memory 中开始,或者您想将原始值保留在寄存器中,请对目标进行异或零处理并使用 SUB/SBB。 SysV x86-32 ABI 在堆栈上传递参数并在 EDX:EAX 中返回 64 位整数。 这就是clang3.9.1 -m32 -O3
所做的,对于neg_value_from_mem
:
; optimal for data coming from memory: just subtract from zero
xor eax, eax
xor edx, edx
sub eax, dword ptr [esp + 4]
sbb edx, dword ptr [esp + 8]
如果您在寄存器中有值并且不需要就地结果,您可以使用NEG将寄存器设置为 0 - 本身,如果输入不为零,则设置 CF。 即与 SUB 相同的方式。 请注意,异或归零很便宜,并且不是延迟关键路径的一部分,因此这绝对比 gcc 的 3 指令序列(如下)更好。
;; partially in-place: input in ecx:eax
xor edx, edx
neg eax ; eax = 0-eax, setting flags appropriately
sbb edx, ecx ;; result in edx:eax
即使对于就地情况,Clang 也会这样做,即使这会花费额外的mov ecx,edx
。 这对于具有零延迟 mov reg,reg(Intel IvB+ 和 AMD Zen)的现代 CPU 的延迟是最佳的,但不适用于融合域 uops 的数量(前端吞吐量)或代码大小。
gcc 的序列很有趣,但不是很明显。 它为就地情况保存了一条指令 vs. clang,但否则情况会更糟。
; gcc's in-place sequence, only good for in-place use
neg eax
adc edx, 0
neg edx
; disadvantage: higher latency for the upper half than subtract-from-zero
; advantage: result in edx:eax with no extra registers used
不幸的是,gcc 和 MSVC 都总是使用它,即使 xor-zero + sub/sbb 会更好。
要更全面地了解编译器的作用,请查看这些函数的输出( 在 Godbolt 上)
#include <stdint.h>
int64_t neg_value_from_mem(int64_t a) {
return -a;
}
int64_t neg_value_in_regs(int64_t a) {
// The OR makes the compiler load+OR first
// but it can choose regs to set up for the negate
int64_t reg = a | 0x1111111111LL;
// clang chooses mov reg,mem / or reg,imm8 when possible,
// otherwise mov reg,imm32 / or reg,mem. Nice :)
return -reg;
}
int64_t foo();
int64_t neg_value_in_place(int64_t a) {
// foo's return value will be in edx:eax
return -foo();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.