Prawdopodobnie „najłatwiejszy”, lub najprostszych, „nie-dbałość o szczegóły” odpowiedzieć jak określić jest:
; 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".
Istnieje szczegółowe uzasadnienie dotyczące ustawiania flag itp. Zawiera również link do kolejnej podobnej odpowiedzi, ale uzasadnienie, dlaczego jest najlepszy sposób z punktu widzenia wydajności. :)
Jak ustawić inny rejestr (będę pick eax
) na 1, gdy ebx
wynosi zero, a na 0, gdy ebx
jest niezerowe (nieniszczących sposobem ebx
sama):
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)
lub jak przerobić ebx
się do 1/0 gdy ebx
jest zero/niezerowe:
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
lub jak konwertować sam ebx
do 1/0 przy ebx
jest zero/niezerowe, inny wariant (szybciej na "P6" na "Haswell" rdzeni):
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
etc, etc ... To zależy od tego, co dzieje się przed testów, a także to, co naprawdę chcesz jako wynik testu, możliwe są różne sposoby (optymalne dla różnych sytuacji i optymalne dla różnych docelowych procesorów).
dodam jeszcze kilka bardzo typowe sytuacje ... licznik pętli w dół licząc od N do zera, do pętli n razy:
mov ebx,5 ; loop 5 times
exampleLoop:
; ... doing something, preserving ebx
dec ebx
jnz exampleLoop ; loop 5 times till ebx is zero
Jak przetwarzać 5 elementów word
(16b) (dostęp do nich w tablicy [0], tablica [1], ...kolejności):
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
Jeszcze jeden przykład, jakoś podobny do tego dużo:
Jak ustawić rejestr docelowy (eax
w przykładzie) do ~ 0 (-1)/0 gdy ebx
jest zero/niezerowe i masz już jakąś wartość 1
w rejestrze (ecx
w przykładzie):
; 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 może wyglądać tak praktyczny jak 1 (dla celów indeksowania s co najmniej), ale -1 działa również jako pełna maska bitowa dla dalszych operacji and/xor/or
, więc czasami jest bardziej przydatny.
Używasz co najmniej instrukcji 80386 ('ebx' nie istnieje w 8086). Również odpowiedź zależy od instrukcji poprzedzających ten kod, obecność wartości zerowej może "przeciekać" według poprzednich instrukcji, oszczędzając jeszcze jednego na teście, w przeciwnym razie typowym idiomem jest 'test ebx, ebx', aby ustawić ZF. Następnie, aby zamienić ZF na wartość 0/1 w ebx, jest inna historia, w której "test" może ponownie nie być częścią optymalnego rozwiązania. Podejmij decyzję, czy chcesz ustalić, czy rejestr jest zerowy, czy też chcesz ustawić jakiś rejestr na 0/1 zgodnie z nim. # 'mov ebx, 0' =' xor ebx, ebx' kiedy możesz niszczyć flagi. – Ped7g
Aby zilustrować mój punkt widzenia (ważność szczegółów), załóżmy, że ostatnią instrukcją modyfikującą flagę (flag AND ebx) była "neg ebx". Wtedy 'sbb ebx, ebx' ustawi' ebx' na -1, gdy 'ebx' będzie równe zero, i na 0 dla niezerowych wartości (dalsze' neg ebx' zamieni to w twój pierwotny 0/1 sposób pracy). – Ped7g
nie działa ze mną. –