大概是“最简单”,或者简单地说,“不关心细节有关”回答如何确定是:
; 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".
有一个详细的answer from Peter Cordes to "testl
eax against eax?" question关于设置标志的推理等。还有一个链接到另一个类似的答案,但推断为什么它是从性能角度来看最好的方式。 :)
如何设置一些其他的寄存器(我会选择eax
)到1时ebx
是零,而设置为0时ebx
非零(非破坏性的方式为ebx
本身):
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)
或如何ebx
转换成自己当1/0为ebx
零/非零:
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
或如何ebx
本身转化为1/0时,ebx
是零/非零的,其他的变种(快上“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
等等,等等...这取决于你在测试之前发生了什么,还你真正想要的作为测试的输出,存在多种可能的方式(对于不同的情况是最佳的,对于不同的目标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
如何处理的word
5个元素( 16b)数组(在数组[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
再举一个例子,我不知何故像这样的很多:
如何设置目标寄存器(eax
例子中)到〜0(-1)/ 0时ebx
是零/非零并且已经有值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
-1可能看起来尽可能的1(用于索引目的至少),但-1还可以作为完整位掩码用于进一步的操作,所以有时它更方便。
您至少使用80386条指令(在8086上不存在'ebx')。此外,答案取决于此代码前面的指令,零值的存在可能会按照前面的指令进行“泄漏”,从而为您节省更多的测试时间,否则常用的习惯用法是'test ebx,ebx'来设置ZF。然后把ZF变成0/1的值是ebx的另一个故事,那里的'测试'可能再次不是最佳解决方案的一部分。下定决心,无论你想确定寄存器是否为零,或者你想根据它设置一些寄存器为0/1。 #'mov ebx,0' ='xor ebx,ebx'当你可以摧毁旗帜时。 – Ped7g
为了说明我的观点(细节的重要性),让我们假设在这之前的最后一个(标志和ebx)修改指令是'neg ebx'。然后'sbb ebx,ebx'会在'ebx'等于零时将'ebx'设置为-1,对于非零值则设为0(进一步'neg ebx'会将其转换为原来的0/1工作方式)。 – Ped7g
没有与我一起工作。 –