Szukaj…


Bezwarunkowe skoki

jmp a_label                      ;Jump to a_label
jmp bx                           ;Jump to address in BX
jmp WORD [aPointer]              ;Jump to address in aPointer
jmp 7c0h:0000h                   ;Jump to segment 7c0h and offset 0000h
jmp FAR WORD [aFarPointer]       ;Jump to segment:offset in aFarPointer

Względne skoki w pobliżu

jmp a_label to:

  • Blisko
    Określa tylko przesuniętą część logicznego adresu docelowego. Zakłada się, że segment to CS .
  • krewny
    Semantyka instrukcji to skok rel bajtów do przodu o 1 od następnego adresu instrukcji lub IP = IP + rel .

Instrukcja jest kodowana jako EB <rel8> lub EB <rel16/32> , asembler wybiera najbardziej odpowiednią formę, zwykle preferując krótszą.
Możliwe jest jmp SHORT a_label dla asemblera, na przykład w NASM jmp SHORT a_label , jmp WORD a_label i jmp DWORD a_label generują trzy możliwe formy.

Bezwzględne pośrednie skoki bliskie

jmp bx i jmp WORD [aPointer] to:

  • Blisko
    Określają tylko część przesunięcia logicznego adresu miejsca docelowego. Zakłada się, że segment to CS .
  • absolutnie pośredni
    Semantą instrukcji jest skok do adresu w reg lub mem lub IP = reg , IP = mem .

Instrukcja jest kodowana jako FF /4 , dla pamięci pośredniej wielkość argumentu określana jest jak dla każdego innego dostępu do pamięci.

Absolutne dalekie skoki

jmp 7c0h:0000h to:

  • daleko
    Określa obie części adresu logicznego : segment i przesunięcie.

  • bezwzględny Semantą instrukcji jest skok do segmentu adresu : offset lub CS = segment, IP = offset .

Instrukcja jest kodowana jako EA <imm32/48> zależności od rozmiaru kodu.
Możliwe jest wybranie jednej z dwóch form w pewnym asemblerze, na przykład w NASM jmp 7c0h: WORD 0000h i jmp 7c0h: DWORD 0000h generuje pierwszą i drugą formę.

Absolutne pośrednie dalekie skoki

jmp FAR WORD [aFarPointer] to:

  • daleko Określa obie części adresu logicznego : segment i przesunięcie.

  • Absolutnie pośredni Semantą instrukcji jest skok do segmentu: przesunięcie zapisane w mem 2 lub CS = mem[23:16/32], IP = [15/31:0] .

Instrukcja jest zakodowana jako FF /5 , rozmiar argumentu może być kontrolerem ze specyfikatorami wielkości.
W NASM, trochę nie intuicyjnie, są one jmp FAR WORD [aFarPointer] dla operandu 16:16 i jmp FAR DWORD [aFarPointer] dla operandu 16:32 .


Brakujące skoki

  • prawie absolutne
    Może być emulowany niemal pośrednim skokiem.

      mov bx, target            ;BX = absolute address of target
      jmp bx
    
  • daleki krewny
    I tak nie ma sensu ani zbyt wąskiego zastosowania.


1 Dwa uzupełnienia służą do określenia przesunięcia ze znakiem, a tym samym przeskoczenia do tyłu.
2 Który może być seg16: off16 lub seg16: off32 , o rozmiarach 16:16 i 16:32 .

Warunki testowe

Aby użyć skoku warunkowego, należy przetestować warunek. Testowanie tutaj warunku odnosi się tylko do sprawdzania flag, rzeczywiste skoki opisano w części Skoki warunkowe .

x86 sprawdza warunki, opierając się na rejestrze EFLAGS, który zawiera zestaw flag, które potencjalnie może ustawić każda instrukcja.

Instrukcje arytmetyczne, takie jak sub lub add , oraz instrukcje logiczne, takie jak xor lub and oczywiście „ustaw flagi”. Oznacza to, że flagi CF , OF , SF , ZF , AF , PF są modyfikowane przez te instrukcje. Dowolna instrukcja może modyfikować flagi, na przykład cmpxchg modyfikuje ZF .

Zawsze sprawdź odniesienie instrukcji, aby wiedzieć, które flagi są modyfikowane przez określoną instrukcję.

x86 ma zestaw skoków warunkowych , o których mowa wcześniej, które skaczą wtedy i tylko wtedy, gdy niektóre flagi są ustawione lub niektóre są czyste lub oba.


Flagi

Operacje arytmetyczne i logiczne są bardzo przydatne w ustawianiu flag. Na przykład po sub eax, ebx , który obecnie przechowuje wartości bez znaku , mamy:

Flaga Po ustawieniu Kiedy będzie jasne
ZF Gdy wynik wynosi zero.
EAX - EBX = 0 ⇒ EAX = EBX
Gdy wynik nie jest równy zero.
EAX - EBX ≠ 0 ⇒ EAX ≠ EBX
CF Kiedy wynik musiał przeprowadzić dla MSb.
EAX - EBX <0 ⇒ EAX <EBX
Kiedy wynik nie musiał nosić dla MSb.
EAX - EBX ≮ 0 ⇒ EAX ≮ EBX
SF Po ustawieniu wyniku MSb. Gdy wynik MSb nie jest ustawiony.
Z Kiedy wystąpił podpisany przepełnienie. Gdy podpisane przepełnienie nie wystąpiło.
PF Gdy liczba bitów ustawiona w najmniej znaczącym bajcie wyniku jest parzysta. Gdy liczba bitów ustawiona w najmniej znaczącym bajcie wyniku jest nieparzysta.
AF Gdy dolna cyfra BCD wygenerowała przeniesienie.
Jest to bit 4 carry.
Gdy dolna cyfra BCD nie wygenerowała przeniesienia.
Jest to bit 4 carry.

Testy nieniszczące

sub i and instrukcje zmieniać ich przeznaczenia operandu i wymaga dwóch dodatkowych kopii (Zapisywanie i przywracanie), aby utrzymać cel niezmodyfikowanej.

Aby wykonać test nieniszczący, należy wykonać instrukcje cmp i test . Są identyczne z ich niszczycielskim odpowiednikiem, z wyjątkiem tego, że wynik operacji jest odrzucany, a tylko flagi są zapisywane .

Destrukcyjny Nieniszczące
sub cmp
and test

test eax, eax             ;and eax, eax
                          ;ZF = 1 iff EAX is zero

test eax, 03h             ;and eax, 03h
                          ;ZF = 1 if both bit[1:0] are clear
                          ;ZF = 0 if at least one of bit[1:0] is set

cmp eax, 241d             ;sub eax, 241d
                          ;ZF = 1 iff EAX is 241
                          ;CF = 1 iff EAX < 241

Testy podpisane i niepodpisane

CPU nie nadaje specjalnego znaczenia rejestrowaniu wartości 1 , znak jest konstrukcją programistyczną. Nie ma różnicy podczas testowania wartości podpisanych i niepodpisanych. Procesor oblicza wystarczającą liczbę flag, aby przetestować zwykłe relacje arytmetyczne (równe, mniejsze niż, większe niż itp.), Zarówno jeśli argumenty mają być uważane za podpisane i niepodpisane.


1 Chociaż zawiera pewne instrukcje, które mają sens tylko w przypadku określonych formatów, takich jak uzupełnienie dwóch. Ma to na celu zwiększenie wydajności kodu, ponieważ wdrożenie algorytmu w oprogramowaniu wymagałoby dużo kodu.

Skoki warunkowe

W zależności od stanu flag procesor może wykonać lub zignorować skok. Instrukcja wykonująca skok na podstawie flag znajduje się pod ogólną nazwą Jcc - Jump on Condition Code 1 .

Synonimy i terminologia

Aby poprawić czytelność kodu asemblera, Intel zdefiniował kilka synonimów dla tego samego kodu stanu. Na przykład jae , jnb i jnc mają ten sam kod warunku CF = 0 .

Chociaż nazwa instrukcji może dać bardzo silną wskazówkę, kiedy jej użyć, czy nie, jedynym sensownym podejściem jest rozpoznanie flag, które należy przetestować, a następnie odpowiedni wybór instrukcji.
Intel podał jednak nazwy instrukcji, które mają idealny sens, gdy są używane po instrukcji cmp . Na potrzeby tej dyskusji zakłada się, że cmp ustawił flagi przed skokiem warunkowym.

Równość

Argumenty są równe, jeśli ustawiono ZF , różnią się inaczej. Aby sprawdzić równość, potrzebujemy ZF = 1 .

je a_label           ;Jump if operands are equal
jz a_label           ;Jump if zero (Synonym)

jne a_label          ;Jump if operands are NOT equal
jnz a_label          ;Jump if not zero (Synonym)
Instrukcja Flagi
je , jz ZF = 1
jne , jnz ZF = 0

Lepszy niż

W przypadku operandów bez znaku miejsce docelowe jest większe niż źródło, jeśli przeniesienie nie było potrzebne, to znaczy, jeśli CF = 0 . Gdy CF = 0 , możliwe jest, że operandy były równe, testowanie ZF będzie jednoznaczne.

jae a_label      ;Jump if above or equal (>=)
jnc a_label      ;Jump if not carry (Synonym)
jnb a_label      ;Jump if not below (Synonym)

ja a_label       ;Jump if above  (>)
jnbe a_label     ;Jump if not below and not equal (Synonym)
Instrukcja Flagi
jae , jnc , jnb CF = 0
ja , jnbe CF = 0, ZF = 0

W przypadku podpisanych argumentów musimy sprawdzić, czy SF = 0 , chyba że wystąpił przepełnienie ze znakiem, w którym to przypadku wynikowa SF jest odwracana. Ponieważ OF = 0, jeśli nie wystąpiło podpisane przepełnienie, a 1 w przeciwnym razie, musimy sprawdzić, czy SF = OF .

ZF może być wykorzystany do wdrożenia testu ścisłego / nie ścisłego.

jge a_label      ;Jump if greater or equal (>=)
jnl a_label      ;Jump if not less (Synonym)

jg a_label       ;Jump if greater (>)
jnle a_label     ;Jump if not less and not equal (Synonym)
Instrukcja Flagi
jge , jnl SF = OF
jg , jnle SF = OF, ZF = 0

Mniej niż

Wykorzystują one powyższe warunki odwrócone.

jbe a_label      ;Jump if below or equal (<=)
jna a_label      ;Jump if not above (Synonym)

jb a_label       ;Jump if below (<)
jc a_label       ;Jump if carry (Synonym)
jnae a_label     ;Jump if not above and not equal (Synonym)

;SIGNED 

jle a_label      ;Jump if less or equal (<=)
jng a_label      ;Jump if not greater (Synonym)

jl a_label       ;Jump if less (<)
jnge a_label     ;Jump if not greater and not equal (Synonym)
Instrukcja Flagi
jbe , jna CF = 1 lub ZF = 1
jb , jc , jnae CF = 1
jle , jng SF! = OF lub ZF = 1
jl , jnge SF! = OF

Określone flagi

Każdą flagę można przetestować osobno za pomocą j<flag_name> gdzie nazwa flagi nie zawiera końcowego F (na przykład CFC , PFP ).

Pozostałe kody, które nie zostały wcześniej uwzględnione, to:

Instrukcja Flaga
js SF = 1
jns SF = 0
jo OF = 1
jno OF = 0
jp , jpe (e = parzysty) PF = 1
jnp , jpo (o = nieparzysty) PF = 0

Jeszcze jeden skok warunkowy (dodatkowy)

Jeden specjalny skok warunkowy x86 nie testuje flagi. Zamiast tego sprawdza wartość rejestru cx lub ecx (w oparciu o aktualny tryb adresu procesora wynoszący 16 lub 32 bity), a skok jest wykonywany, gdy rejestr zawiera zero.

Ta instrukcja została zaprojektowana do sprawdzania poprawności rejestru licznika ( cx/ecx ) przed instrukcjami podobnymi do rep lub przed loop pętli.

jcxz  a_label   ; jump if cx (16b mode) or ecx (32b mode) is zero
jecxz a_label   ; synonym of jcxz (recommended in source code for 32b target)
Instrukcja Zarejestruj się (bez flagi)
jcxz , jecxz cx = 0 (tryb 16b)
jcxz , jecxz ecx = 0 (tryb 32b)

1 Lub coś takiego.

Sprawdź relacje arytmetyczne

Nieoznaczone liczby całkowite

Lepszy niż

cmp eax, ebx
ja a_label  

Większy bądź równy

cmp eax, ebx
jae a_label  

Mniej niż

cmp eax, ebx
jb a_label  

Mniejszy lub równy

cmp eax, ebx
jbe a_label 

Równy

cmp eax, ebx
je a_label 

Nie równe

cmp eax, ebx
jne a_label     

Podpisane liczby całkowite

Lepszy niż

cmp eax, ebx
jg a_label  

Większy bądź równy

cmp eax, ebx
jge a_label  

Mniej niż

cmp eax, ebx
jl a_label  

Mniejszy lub równy

cmp eax, ebx
jle a_label 

Równy

cmp eax, ebx
je a_label 

Nie równe

cmp eax, ebx
jne a_label 

a_label

W powyższych przykładach a_label jest miejscem docelowym dla procesora, gdy testowany warunek jest „prawdziwy”. Gdy testowany warunek jest „fałszywy”, procesor będzie kontynuował następną instrukcję po skoku warunkowym.

Synonimy

Istnieją synonimy instrukcji, które można wykorzystać do poprawy czytelności kodu.
Na przykład ja i jnbe (Skok nie niższy ani równy) są tą samą instrukcją.

Podpisano niepodpisane kody towarzyszące

Operacja Bez podpisu Podpisany
> ja jg
> = jae jge
< jb jl
<= jbe jle
= je je
≠,! =, <> jne jne


Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow