Loops 在x86/x86_64中,我如何;如果不是零,则跳转“;不影响进位标志?
我有一个循环,它本质上是添加两个动态宽度整数(实际上,它稍微展开了一点,但这在这里并不重要)。寄存器Loops 在x86/x86_64中,我如何;如果不是零,则跳转“;不影响进位标志?,loops,assembly,x86,compare,x86-64,Loops,Assembly,X86,Compare,X86 64,我有一个循环,它本质上是添加两个动态宽度整数(实际上,它稍微展开了一点,但这在这里并不重要)。寄存器RCX包含目标地址,RDX包含源地址,R8包含数组长度 clc # Clear CF flag before beginning .Lloop0: movq (%rdx), %rax # Load memory for next addition adcq %rax, (%rcx) # Perform additio
RCX
包含目标地址,RDX
包含源地址,R8
包含数组长度
clc # Clear CF flag before beginning
.Lloop0:
movq (%rdx), %rax # Load memory for next addition
adcq %rax, (%rcx) # Perform addition with carry (i.e. using CF flag)
leaq 8(%rcx), %rcx # Increment destination address (without affecting CF)
leaq 8(%rdx), %rdx # Increment source address (without affecting CF)
leaq -1(%r8), %r8 # Decrement length (without affecting CF)
testq %r8, %r8 # Test if length is zero (affects CF!)
jne Lloop0
问题在于TEST
指令清除了CF
标志,这是下一个ADC
所需要的。CMP
指令也会产生类似的效果
当然,我可以在测试之前使用
LAHF
复制标志
寄存器,并在循环开始时使用SAHF
还原它,但如果有办法,我希望避免这种情况。您可以交换上面%r8
和%rcx
的角色以产生:
clc
.p2align 4 # just a thought...
.Lloop0:
jrcxz .Lloop0_end
...
leaq -1(%rcx), %rcx
jmp .Lloop0
.Lloop0_end:
您可以使用
dec%r8
,但请注意,不建议这样做,因为不更新CF
会导致部分标志寄存器暂停:)它会自动设置ZF
。您只需执行dec%r8;jnz Lloop0
。或者,您可以重写代码以使用rcx
作为计数器,然后使用循环
指令(这也是不推荐的,但不如dec
:)x86 CPU是复杂的。JNZ
将根据分支预测推测执行,因此如果您多次循环,它应该是有效的。您还可以使用rcx
(而不是r8
)作为计数器和循环
指令。loop
指令隐式地使用rcx
作为计数器,并且不影响进位标志。如果rcx
不为零,则不会出现类似于JRCXNZ
的情况。不,这不存在,@matt。但实际上没有理由使用jrcxz
或神秘的jrcxnz
。这比将指令分成两部分要慢。