Zey*_*man 6 x86 assembly micro-optimization
我正在使用与Irvine库的x86程序集.
检查寄存器值是否等于零的最简单方法是什么?
我使用cmp指令,但我正在寻找替代方法.这是我使用cmp指令的代码,寄存器是ebx
cmp ebx,0
je equ1
mov ebx,0
jmp cont
equ1:
mov ebx,1
jmp cont
cont:
exit
Run Code Online (Sandbox Code Playgroud)
这个"booleanizes"一个值,int ebx = !!ebx在C中产生0或1 .
Ped*_*d7g 11
可能最"最简单",或最简单,"不关心细节"的答案如何确定是:
; here ebx is some value, flags are set to anything
test ebx,ebx ; CF=0, ZF=0/1 according to ebx
jz whereToJumpWhenZero
; "non-zero ebx" will go here
; Or you can use the inverted "jnz" jump to take
; a branch when value was not zero instead of "jz".
Run Code Online (Sandbox Code Playgroud)
彼得·科德斯(Peter Cordes)testl有一个详细的答案是" 对抗eax?" 关于标志被设置的问题推理等.还有一个链接到另一个类似的答案,但从性能的角度推断为什么它是最好的方式.:)
eax当ebx零为零时,如何将其他寄存器(我将选择)设置为1,当非零时ebx(非破坏性ebx自身方式)将如何设置为0 :
xor eax,eax ; eax = 0 (upper 24 bits needed to complete "al" later)
test ebx,ebx ; test ebx, if it is zero (ZF=0/1)
setz al ; al = 1/0 when ZF=1/0 (eax = 1/0 too)
Run Code Online (Sandbox Code Playgroud)
或者ebx当ebx零/非零时如何将自身转换为1/0 :
neg ebx ; ZF=1/0 for zero/non-zero, CF=not(ZF)
sbb ebx,ebx ; ebx = 0/-1 for CF=0/1
inc ebx ; 1 when ebx was 0 at start, 0 otherwise
Run Code Online (Sandbox Code Playgroud)
或者ebx当ebx零/非零时如何将自身转换为1/0 ,其他变体("P6"到"Haswell"核心更快):
test ebx,ebx ; ZF=1/0 for zero/non-zero ebx
setz bl ; bl = 1/0 by ZF (SETcc can target only 8b r/m)
movzx ebx,bl ; ebx = bl extended to 32 bits by zeroes
Run Code Online (Sandbox Code Playgroud)
等等......这取决于你的测试之前发生了什么,以及你真正想要的测试输出,有很多可能的方法(最适合不同的情况,最适合不同的目标CPU).
我将添加一些非常常见的情况......一个从N到零的反向循环计数,循环N次:
mov ebx,5 ; loop 5 times
exampleLoop:
; ... doing something, preserving ebx
dec ebx
jnz exampleLoop ; loop 5 times till ebx is zero
Run Code Online (Sandbox Code Playgroud)
如何处理word(16b)数组的5个元素(在数组[0],数组[1],......顺序中访问它们):
mov ebx,-5
lea esi,[array+5*2]
exampleLoop:
mov ax,[esi+ebx*2] ; load value from array[i]
; process it ... and preserve esi and ebx
inc ebx
jnz exampleLoop ; loop 5 times till ebx is zero
Run Code Online (Sandbox Code Playgroud)
还有一个例子,我在某种程度上喜欢这个:
eax当ebx零/非零时,如何将目标寄存器(例如)设置为~0(-1)/ 0,并且1在某些寄存器中已经有值(ecx例如):
; ecx = 1, ebx = some value
cmp ebx,ecx ; cmp ebx,1 => CF=1/0 for ebx zero/non-zero
sbb eax,eax ; eax = -1 (~0) / 0 for CF=1/0 ; ebx/ecx intact
Run Code Online (Sandbox Code Playgroud)
-1可能看起来像1一样实用(至少用于索引),但-1也可用作进一步and/xor/or操作的完整位掩码,因此有时它更方便.