FAQ CrackPL - Asm dla badaczy kodu - Wprowadzenie
Chyba nikogo nie musze uswiadamiac jak wazna jest znajomosc
assemblera dla badaczy kodu. Jezyk ten bedacy mnemonika kodu
maszynowego procesorow ulega zatraceniu w dzisiejszych czasach w
dobie pakietow typu Visual Microsoftu, Borlanada i innych.
Nowoczesni (czytaj. nowi -:)) programisci nie maja nawet pojecia
czym jest assebler i jak go ugrysc a przeciez kod asemblera jest
esencja programowania i dlatego kazdy badacz kodu musi go poznać.
Postanowilem przedstawic wam maly guide wprowadzajacy do asemblera
dla wszystkich poczatkujacych crackerów i pod ich kierunkiem
pisany. Jest to jedynie schematyczny przeglad podstawowych pojec i
instrukcji, który mam nadzieje rozwine w przyszlosci. W ZADNY
WYPADKU NIE JEST TO TUTOR programowania w asm, jedynie przedstawia
zagadnienia na ktore nalezy zwrocic uwage podczas analizy kodu. No
ale mam nadzieje :-) ze kazdy kto to przeczyta wezmie sie za asm'a
porzadnie i bedzie pisal w nim programy w razie potrzeby.
Wszelkie sugestie i pomysly kierowac na gcrkpl@friko6.onet.pl.
Co powinien wiedziec cracker o asm
InDeX
[PODSTAWOWE INFORMACJE]
1. Rejestry [REGISTERS]
1.a. [Specyfikacja architektury Intela - Rejestry]
2. [Flagi - Rejestr znacznikow]
2.a. [Flagi - Rejestr znacznikow - specyfikacja Intel 8086]
3. [Stos - STACK ]
4. [Call i Ret - wywolania funkcji i procedur]
5. [MOV - instrukcja przeniesienia]
6. [CMP i skoki warunkowe]
6.a. [Specyfikacja skokow warunkowy]
[CIEKAWOSTKI]
7. TEST EAX,EAX - co to znaczy ?
___________________________________________________________________
1. Rejestry [REGISTERS]
Rejestry sa podstawowym miejscem przechowywania danych. Sa to
16-bitowe komorki procesora. Jest 14 rejestrów i w tym 12 rejestrow
danych i adresowych, rejestr wskaznika instrukcji (IP) i rejestr
znacznikow. Rejestry danych i adresowych mozemy podzielic na kilka
grup i tak:
AX (akumulator) --------+
BX (bazowy) |----- Rejestry ogólnego
przenzaczenia
CX (licznik) |
DX (danych) --------+
SP (wskaznik stosu) --------+
BP (wskaznik bazy) |-----Rejestrywskaznikowe i
indeksowe
SI (index zrodla) |
DI (indeks przeznaczenia) --------+
CS (programu) --------+
DS (danych) |----- Rejstry segmentowe
SS (stosu) |
ES (dodatkowy) --------+
IP (wskaznik instrukcji)
I Rejestr Znacznikow
Jak oczywiscie kazdy sie zorientowal przy pracy w Win32 rejestry
okreslane sa jak EAX, EAX itd, oznacza to ze sa to odpowiedniki
powyzszych rejestrow, tyle, ze 32-bitowe.
Chwila wyjasnienia z tymi bitami. Wezmy rejestr AX, ktoryjest 16
bitowy i dzieli sie na dwa podrejestry 8 bitowe AH i AL. Jak wiemy
8 bitow tworzy bajt, ktory przyjumuje wartosc od 0 do 255, czyli
rejestr AH i AL moze miec najwieksza wartosc FFh. Logicznie myslac
-:) rejestr 16 bitowy moze przyjac maksymalna wartosc FFFFh itd.
(32 bit EAX mam max FFFFFFFFh ups-:)). Chyba kazdy lapie co daja 32
bitowe rejestry i jak zwiekszaja sie mozliwosci.
Warto zapoznac sie z charakterystykami rejestrow, gdzyz kazdy ma
swoje wlasne konkretne zastowsowanie. Przegladajac kod programu
mozemy zauazyc pewne prawidlowosci, np.
EIP - debugujac pod SoftIce 32bit widzimy, ze rejestr ten wskazuje
na aktualny kod instrukcji i mozemy go uzyc np do zalozenia pulapki
na danej lini czyli bpx EIP lub dokladniej CS:EIP.
CS - wskazuje segment kodu, czyli jak mamy jakac linie kodu o
adresie np. 14F:04033232 to mozemy ja zapisac jako CS:04033232
poniewaz w rejestrze CS jest zachowana wartosc 014F.
DS - podobnie jak powyzej, zawiera adres segmentu dany, jezeli w
okienku danych pod SoftIce mamy jakis adres np. 0145:03055555 to DS
wskazuje segment 0145.
ESI i EDI sa wskaznikami danych np. do porownan tekstow itp. Wezmy
np. instrukcje porownywania w bibliotekach VB - reps cmpsw dla,
ktorych w w ds:esi i es:edi zawarte sa adresy tekstow (np. numerow
seryjnych) do porwnania. To samo tyczy sie wielu instrukcji
przesylania i porownnywania danych, gdzie przeznaczenie i cel
zawarte sa w rejesteach SI i DI np:
LEA SI, ZRODLo ;Zaladowanie adresu zrodla
LEA DI, ES:PRzesznaczenie ;Zaladowanie adresu
przezanczenia
MOV CX,100 ;Zaladowanie licznika elementow
MOVS Przeznaczenie,Zrodlo ;Kopiowanie tekstu z jednego
miejsca w innne.
___________________________________________________________________
1.a. [Specyfikacja architektury Intela - Rejestry]
Rejestry ogolnego przeznaczenia Rejestrysegmentowe
AH/AL AX (EAX) Akumulator CS Programu
BH/BL BX (EBX) Bazowy DS Danych
CH/CL CX (ECX) Licznik SS Stosu
DH/DL DX (EDX) Danych ES Dodatkowy
(Exx) znaczy 386+ 32 bit rejestr
Rejestry wskaznikowe Rejestry stosu
SI (ESI) Indeks zrodla SP (ESP) Wskaznik stosu
DI (EDI) Indeks przeznaczenia BP (EBP) Wskaznik bazy
IP Wskaznik instrukcji
FLAGI Rejestr Znacznikow (zobacz FLAGI)
Specjalne rejestry (386+)
CR0 Control Register 0 DR0 Debug Register 0
CR2 Control Register 2 DR1 Debug Register 1
CR3 Control Register 3 DR2 Debug Register 2
DR3 Debug Register 3
TR4 Test Register 4 DR6 Debug Register 6
TR5 Test Register 5 DR7 Debug Register 7
TR6 Test Register 6
TR7 Test Register 7
Rejestry ogolnego przeznaczenia sa przeznaczzone do przechowywania
dowolnych danych i wykonywania roznych operacji (arytmetycznych,
logicznych itp) , pelnia takze funkcje specjalne odpowiadajace ich
nazwom.
AX (accumulator) - rejestr ten jest najczesciej uzywany przy
operacjach mnozenia i dzielenia, a takze w operacjach logicznych,
arytmetycznych i odkladania wynikow wielu operacji.
8 dolnych bitow tego rejstru okresla sie jako rejestr AL, a 8
gornych bitow jako AH
BX (basis) - rejestr bazowy moze byc uzywany jako dwa 8-bitowe
rejestry BH i BL, a np. jako 16-bit mozemy go uzyc do utworzenia
adresu pamieci, tworzac z rejestrem segmentowym pelny adres -
Segmennt:Offset - DS:BX
CX (count) - rejestr zliczajacy jest wykorzystywany oprocz
zliczania takze do przesylania danych. Moze byc takze uzywany jako
dwa rejestry 8-bitowe CH i CL.
DX (data) - rejestr danych wykorzystuje sie przy dzieleniu i
mnozeniu. Jest takze jedynym rejestrem, w korym mozna podac adres
portu w rozkazach wejscia-wyjscia.
Rejestry segmentowe sluza do adresowania pamieci operacyjnej.
CS (code segment) - rejestr wskazuje poczatek segmentu kodu
programu, tworzy pelny adres wraz z rejestrem IP - CS:IP. Rozkazy
programu, skoki, powroty pobierane sa w odniesieniu do tego
rejestru.
DS (data segment) - rejestr wskazujacy poczatek segmentu danych
SS (stack segment) - rejestr stosu wskazuje poczatek segmentu stosu
ES (extra segment) - rejestr dodatkowu wskazujacy dodatkowy segment
danych
Rejestry wskaznikow. Dostep do danych adresowany jest przez
polaczenie adresu z rejestru segmentu z przesunieciem pobieranym z
innego rejestru min. rejestru wskaznikowego.
SI (source index) - rejestr indeksowy zrodla, najczesciej stosowany
przy adresowaniu w innstrukcjach przetwarzajacych lancuchy znakow,
tworzy wowczas pelny adres DS:SI
DI (destination index) - rejestr indeksowy przeznaczenia, podobny
do SI uzywany w adresowaniu danych przy przetwarzaniu lancuchow
znakow, tworzy wowczas pelny adres ES:DI
SP (stack pointer) - wskaznik stosu tworzy wraz z SS - SS:SP adres
danej odeslanej na stos i jest wykorzystywany przy pobieraniu i
zapisywaniu danych na stos.
BP (base pointer) - wskaznik bazy uzywany jest podczas operacji
niestandardowych np. przy pobieraniu parametrow przekazywanych na
stos.
IP (instruction pointer) - wskaznik instrukcji wskazuje na
aktualnie wykonywana instrukcje i wraz z rejestrem segmentu kodu
tworzy pelny adres - CS:IP. IP wskazuje offset (przesuniecie)
wzgledem poczatku segmentu programu.
___________________________________________________________________
2. [Flagi - Rejestr znacznikow]
Falgi sa komorkami, ktore moga przyjmowac wartosc 0 lub 1 i sa
zawarte w rejestrze znacznikow. Odpowiednie ustawienie
poszczegolnych flag decyduje o wykonaniu innych instrukcji a
szczegolnie instrukci warunkowych. Najszybciej zrozumiec flagi
mozna na przykladzie :
CMP AX,BX - Porownaj rejestry AX z BX, jezeli rowne to flaga
zerowa Z ustawiona na 1
JZ 0401233 - Jezeli flaga Z ustawiona na 1 to wykonaj skok do
adrsu 0401233
Oczywiscie intrukcja CMP ustawia takze inne flagi z zaleznosci od
wyniku porownania i podobnie inne instrukcje warunkowych skokow
moga sprawdzac takze inne flagi. Szczegolowiej przedstawie to przy
omowieniu skokow warunkowych.
Po co nam znajomoasc flag, ano poto aby podzczas analizy kodu
wiedziec jaki wynik dalo porownanie danych i czy np. skok zostanie
wykonany czy nie. Poza tym debugujac program mozem zmienic
dzialanie instrukcji skoku zmieniajac stan znacznikow.
Np. w powyzszym przykladzie AX jest rowne BX i flaga zerowa Z
zostala ustawiona na 1 wiec skok warunkowy zostanie wykonany.
Jezeli jednak mimo rownosci AX i BX nie chcemy wykonac skoku to
podczas sledzenia programu resetujemy flage zerowa. W SoftIce
robimy to : r fl z (czyli resetuj flage zerowa) i skok nie zostanie
wykonany :-)
Ciekawostki :
Bit 6 rejestru znacznikow - znacznik zera, najwazniejsza przy
pierwszych krokach lamania programow. Decyduje o podstawowych
skoksach warunkowych :-)
Bit 8 rejestru znacznikow - flaga pracy krokowej (TF - trap flag)
ustawia procesor w trybie pracy krokowej w celu uruchomienia
programu pod debugerem,
Bit 10 rejestru znacznikow - flaga kierunku (DF - direction flag)
wymusza zwiekszania lub zmniejszanie rejestrow indeksowych przy
wykonywaniu instrukcji operujacych na lancuchach czyli albo rosnaco
albo malejaco (czyli od lewej do prawej albo na odwrot). Czujecie,
przeciez numer seryjny mozna spokojnie przeczytac od koncz :-)
___________________________________________________________________
2.a. [Flagi - Rejestr znacznikow - specyfikacja Intel 8086]
Rejestr znacznikow jest 16-bitowym rejestrem, szesc bitow zawiera
informacje o stanach, trzy pozwalaja sterowac praca procesora z
poziomu programu a dwa pozostale zwiazane sa z trybem wirtualnym.
|11|10|F|E|D|C|B|A|9|8|7|6|5|4|3|2|1|0|
| | | | | | | | | | | | | | | | | '--- CF Carry Flag
| | | | | | | | | | | | | | | | '--- 1
| | | | | | | | | | | | | | | '--- PF Parity Flag
| | | | | | | | | | | | | | '--- 0
| | | | | | | | | | | | | '--- AF Auxiliary Flag
| | | | | | | | | | | | '--- 0
| | | | | | | | | | | '--- ZF Zero Flag
| | | | | | | | | | '--- SF Sign Flag
| | | | | | | | | '--- TF Trap Flag (Single Step)
| | | | | | | | '--- IF Interrupt Flag
| | | | | | | '--- DF Direction Flag
| | | | | | '--- OF Overflow flag
| | | | '----- IOPL I/O Privilege Level (286+ only)
| | | '----- NT Nested Task Flag (286+ only)
| | '----- 0
| '----- RF Resume Flag (386+ only)
'------ VM Virtual Mode Flag (386+ only)
Bit 0, (CARRY FALG) CF - Znacznik przeniesienia, ma wartosc 1 jesli
dodawanie powoduje przeniesienie lub odejmowanie powoduje
pozyczenie, w przeciwnym razie ma wartosc 0. CF zawiera takze
wartosc przesuniecia lu przesunietego cyklicznie bitu wychodzacego
poza rejestr lub komorke pamieci, oddaje takze wynik operacji
porownania. CF dziala takze jako wskaznik dla operacji mnozenia.
Bit 2, (PARITY FLAG) - Znacznik parzystosci - ma wartosc 1 gdy
wynik operacji ma parzysta ilosc bitow o wartosci 1, w przeciwnym
wypadku znnacznik przyjmuje wartosc 0. PF jest glownie uzywany przy
przesylaniu danych.
Bit 4, (AUXILIARY CARRY FLAG) - znacznik przeniesienia pomocniczego
- ma podobne znaczenie jak CF, ale pokazuje przeniesienie lub
pozuczke od bitu 3 w gore. AF jest uzyteczny przy dzialaniach na
"spakowanych" liczbach dziesietnych.
Bit 6, (ZERO FLAG) - znacznik zera - ma wartosc 1 gdy wynik
operacji jest zerem, wynik rozny od zera ustawia na 0
Bit 7 - (SIGN FLAG) - znacznik znaku - ma znaczenie tylko podczas
operacji na liczbach ze znakiem, SF przyjmuje wartosc 1 jesli
wynikiem operacji arytmetycznych, logicznych, przesunniec jest
wartosc ujemna, w przeciwnym wypadku przyjmuje wartosc 0. Inaczej
mowiac SF pokazuje najbardziej znaczasy bot (bit znaku) wyniku,
niezaleznie czy wynik jest 8 czy 16-bitowy
Bit 8 - (TRAP FLAG) - znacznik pracy krokowej - ustawia procesor w
trybie pracy krokowej, w celu uruchomienia programu po debugerem.
Bit 9 - (INTERRUPT FLAG) - znacznik zezwolenia na przerwanie -
zezwala procesorowi rozpoznac zadanie obslugi przerwan pochodzace
od zewnetrznych urzadzen systemu. Wyzerownie IF powoduje, ze
procesor ignoruje przerwania.
Bit 10 - (DIRECTORY FLAG) - znacznik kierunku - wymusza
zmniejszenie (DF=1) lub zwiekszenie (DF=0) rejestrow indeksowych po
wykoniu instrukcji operujacych na lancuchach. Jesli DF =0 to
procesor przetwarza lancuchy w kierunku rosnaczych adresow (od
strony lewej do prawej) a jak 1 to w kierunku odwrotnym.
Bit 11 - (OVERFLOW FLAG) - znacznik nadmiaru - jest glownie
wskaznikiem bledu podczs operacji na liczbaczh ze znakiem.
OF=1 jesli dodanie dwoch liczb z jednakowym znakiem lub odjecie
dwoch liczb z roznymi znakami daje wynik nie mieszczacy sie w
argumencie wykonanej instrukcji, w przeciwnym przypadku znacznik
jest 0. OF ma takze wartosc 1 gdy najbardzej znaczacy bit (bit
znaku) argumentu zostanie zmieniony przez przesuniecie podczas
operacji arytmetycznej, w przeciwnym przypadku jest 0.
Znacznik OF, razem ze znacznikiem CF, wskazuje takze dlugosc wyniku
mnozenia. Jesli bardziej znaczaca czesc iloczynu jest rozna od zera
to OF i CF sa rowne 1, jezeli jest inaczej to oba znaczniki sa
rowne 0.
OF takze przyjmuje wartosc 1 gdy operacja z dzielenia daje iloraz
przekraczajacy rejestr przeznaczenia.
___________________________________________________________________
3. [Stos - STACK ]
Stos jest miejscem przechowywania danych jak rejestry lub
zawartosci komorek pamieci. Mamy dwie instrukcje PUSH, ktora
przesyla dane na szczyt stosu i POP, ktora pobiera dane ze szczytu
stosu. O co biega z tymi szczytami :-), stos jest sterta na ktorej
ukladane sa dane, kazda dana ukladana jest na szczyt a poprzednia
dana schodzi na dalsza pozycje. Czyli istotna jest kolejnosc
kladzenia danych na stos, gdyz w takiej samej( a dokladnie
odwrotnej) kolejnosci musimy pobierac dane ze stosu:
PUSH EAX - kladzie na szczyt stosu EAX
PUSH EBX - kladzie na szczyt stosu EBX a EAX schodzi na dalsza
pozycje
....instrukcje
POP EBX - pobiera ze szczytu dana ktora jest EBX ( a na szczycie
zostaje EAX)
POP EAX - pobiera ze szczytu stosu EAX
Chyba lapiecie o co biega ?:-)
Acha jeszcze jedno, na szczyt stosu wskazuje tzw. wskaznik stosu SP
(Stack Pointer) a instrukcje PUSH i POP zwiekszaja i zmniejszaja
ten wskaznik. Rejestr ten nigdy nie jest ustawiany bo procesor to
robi automatycznie i zawsze wskazuje adres szczytu stosu
(szczytowego slowa).
Paczac ogolnie na pamiec komputera, kazda czesc programu moze
utworzyc swoja dowolna przestrzen stosu. Programista powinien tak
przydzielic pamiec aby stos nie pokrywal sie przypadkiem z innymi
obszarami pamieco :-)
___________________________________________________________________
4. [Call i Ret - wywolania funkcji i procedur]
CALL adres wywoluje funkcje o podanym adresie i wykonuje ja az do
powrotu (RET).
instrukcje...
CALL 040ABCCC
Mov eax,edx
instrukcje...
Wywollanie CALL wywola funkcje o adrsie 040ABCCC i po powrocie z
niej (RET) program bedzie kontynuowal dalej MOV eax,edx itd. Jak to
sie dzieje, ze program wie gdzie ma wrocic ?. Ano CALL kladzie
adres kodu na stosie, natomiast RET pobiera ten adres i wraca tam
gdzie potrzeba.
Jezeli CALL wywoluje jakies funkcje, to argumenty takiej funkcji
kladziemy na stosie przed wywolanie CALL. Przyklad takiego
dzialania :
MOV EDI,[ESP+00000220] Zapisuje uchwyt okienka dialogowego w EDI
PUSH 00000100 Maksymalny rozmiar tekstu na stos
PUSH 00406130 Adres bufora dla tekstu na stos
PUSH 00000405 Identyfikator na stos
PUSH EDI Uchwyt okienka dialogowego na stos
CALL GetWindowText Wywolanie funkcji o parametrach zapisanych
na stosie.
Widzimy wiec, ze przy jakis ciekawych wywolania funkcji warto
zagladnac jakie parametry kladzione sa na stosie i ogolnie warto
sie zorientowac jakie parametry dana funkcja wymaga.
___________________________________________________________________
5. [MOV - instrukcja przeniesienia]
To najczesciej spotykana instrukcja umozliwiajaca przenoszenie
danych pomiedzy rejestrem a komorka lub pomiedzy rejestrami lub
kopiowania stalej wartosci do rejestru lub komorki.
Ogolna postac to MOV przeznaczenie, zrodlo i nie powinno nikomu
sprawic klopotu jej zrozumienie.
Przyklady :
MOV EDS, EAX - przeniesienie pomiedzy dwoma rejestrami
32-bitowymi
MOV CL, 39 - przeniesienie stalej do rejestru
MOv ES:[BX],AX - zmiana przypisania segmentu
Kila uwag :
1). Nie mozna bezposrednio przeniesc danych pomiedzy komorkami
pamieci. Musimy dane najpier przeniesc dane do rejestru ogolnego
przeznaczenia a pozniej z rejestru do przeznaczenia w pamieci.
Przyklad, mamy dwie zmienne w pamieci np. TYLEK i ZADEK i aby
przenies wartosc z jednej do drugiej to
MOV AX,TYLEK
MOV ZADEK,AX
2). Nie mozna zaladowac bezposrednio stalej do rejestru segmentu,
musimy ja przenies przez rejestr ogolnego przeznaczenia.
MOV AX, ADRES_DS
MOV DS, AX
3). Podobnie nie mozemy przenies bezposrednio zawartosci jednego
rejestru segmentu do drugiego, podobnie musimy przez rejestr
ogolnego przeznaczenia.
MOV AX, ES
MOV DS, AX
4). Nie mozna uzyc rejestru CS jaki argumentu przeznaczenia w
instrukcji MOV
Widzicie wiec jakie kombinacje nalezy wykonywac z danymi i dlaczego
az tak duzo instrukcji MOV mamy w kodzie programu.
Przy debugowaniu programu pamietajcie, ze w rejestrze moze byc
szukana przez nas wartosc lub adres wskazujacy na ta szukana
wartosc. A wiec sprawdzajac w SOFTICE dane jezeli uzyjemy komendy
np. d EAX to wyswietli nam w oknie danych zawartosc pamieci o
adresie zawartym w EAX, natomiast jak damy ? EAX to wyswietli nam
dane zawarte w EAX w postaci szesnastkowej i dziesietnej.
___________________________________________________________________
6. [CMP i skoki warunkowe]
Bardzo wazna instrukcja jest CMP (compare), ktora decyduje o
dzialaniu programu, petlach, skokach, wywolaniach podprogramow itp.
Instrukcaja CMP dziala na zasadzie odejmowania zrodla od
przeznaczenia i sprawdzaniu otrzymandego wyniku. Glownym celem
dzialania tej instrukcji jest ustawienie rejestrow w zaleznosci od
otrzymanego wynniku. W przypadku operacji na argumentach bez znaku
ustawiane sa dwie flagi - zerowa ZF i przeniesienia CF, natomiast
przy operacjach na argumentach ze znakiem dodatkowo jeszcze -
nadmiaru OF i znaku SF
Przyklad:
CM AX,BX - jezeli AX = BX to ZF=1 i CF=0 gdy AX > BX to ZF=0 i CF=1
gdy AX < BX to ZF i CF=0
Na podstawie spelnianych warunkow, czyli ustawieniu poszczegolnych
flag moga nastapic skoki warunkowe w kodzie. Naczesciej spotykany
JZ - skok jezeli ustawiona flaga Z czyli np. w przypadku porownaia
czy AX=BX i jezeli tak to skok.
Podobna instrukcja jest TEST, ktora dla odmiany przeprowadza
operacje logiczna na bajtach - AND ale nie zapamietuje wyniku a
jedynie na jego podstawie ustawia odpowiednio flagi.
Przyklad: CALL procedura procedura: MOV AX,1
TEST AX,AX CMP
Wpisany_kod, Dobry_kod
JZ adres2 JE dobrywpis
RET
dobrywpis: XOR
AX,AX
RET
Procedura CALL wywoluje np. procedure sprawdzania poprawnosci
danych rejestracyjnych i w przypadku pomyslnym zapisuje do AX
wartosci logiczna 0 (np. przez XOR AX,AX) a jezeli zle to zapisuje
1. Teraz instrukcja TEST AX,AX wykonuje operacje logiczna na AX
czyli AX and AX, jezeli bylo (0 to 0) AND 0 da nam 0 i flaga zerowa
Z zostaje ustawiona na 1. Teraz instrukcja skoku warunkowego
sprawdza czy flaga zerow Z=1 i robi skok. Natomiast gdy by bylo (1
AND 1) to flaga Z=0 i skok nie nastapi.
A procedurka to wiadomo, napoczatku wpisujemy wartosc logiczna 1 do
AX (czyli zly kod) a pozniej sprawdzamy jaki faktycznie jest
wpisany kod, jezeli poprawny to skok i operacja (1 XOR 1) co da nam
0 w AX i powrot a jak zly to niech pozostanie 1 i powrot
Nalezy pamietac, ze instrukcje CMP i TEST wykonuja operacje na
argumentach, ktorych wykonanie ustawia kilka odpowiednich flag w
zaleznosci od wielkosci argumentow, znaku, przeniesienia itp.
Dlatego tez mozemy wykonac odpowiednie skoki nie tylko przy warunku
A=B ale tez w zaleznosci czy mniejsze, wieksze, ze znakiem itp.
Np. skok JA (skok gdy powyzej) wykonany jest gdy flagi CF=0 i ZF=0
i wykonuje skok gdy przeznaczenie jest wieksze od zrodlo (bo to
wyniklo z operacji porownania i takiego ustawienia flag). Od razu
zaznaczam, ze analizujac kod pod SoftIce aby zmienic skok np.
musimy nie tylko zmienic flage Z ale i C (czyli np. r fl z; r fl
c). To samo tyczy sie innych skokow warunkowych i zapraszam do
tabeli specyfikacji skokow warunkowych.
___________________________________________________________________
6.a. [Specyfikacja skokow warunkowy]
Instrukcja Opis Skok jesli.....
JA skok gdy powyzej CF=0 i ZF=0
JAE skok gdy powyzej lub rowny CF=0
JB skok gdy ponizej CF=1
JBE skok gdy ponizej lub rowny CF=1 or ZF=1
JC skok gdy przeniesienie CF=1
JCXZ skok gdy CX=0 CX=0
JE skok gdy jest rowny ZF=1
JG skok gdy wiekszy * ZF=0 and
SF=OF
JGE skok gdy wiekszy lub rowny * SF=OF
JL skok gdy mniejszy SF != OF
JLE skok gdy mniejszy lub rowny * ZF=1 or SF
!= OF
JMP skok bezwarunkowy bez warunku
JNA skok gdy nie powyzej CF=1 or ZF=1
JNAE skok gdy nie powyzej ani rowny CF=1
JNB skok gdy nie ponizej CF=0
JNBE skok gdy nie ponizej ani rowny CF=0 and
ZF=0
JNC skok gdy nie ma przeniesienia CF=0
JNE skok gdy nie rowny ZF=0
JNG skok gdy nie wiekszy ZF=1 or SF
!= OF
JNGE skok gdy nie wiekszy ani rowny * SF != OF
JNL skok gdy nie mniejszy * SF=OF
JNLE skok gdy nie mniejszy ani rowny * ZF=0 and
SF=OF
JNO skok gdy niema przepelnienia * OF=0
JNP skok gdy nie parzystosc PF=0
JNS skok gdy brak znaku * SF=0
JNZ skok gdy rozne od zera ZF=0
JO skok gdy jest przepelnienie * OF=1
JP skok gdy parzystosc PF=1
JPE skok gdy parzystosc parzysta :-) PF=1
JPO skok gdy parzystosc nieparzysta PF=0
JS skok gdy jest znak * SF=1
JZ skok gdy jest zero ZF=1
* - wazne dla arytmetyki liczb ze znakiem (uzupelnienie do dwoch)
___________________________________________________________________
7. TEST EAX,EAX - co to znaczy ?
Powyzsza linia kodu wydaje sie niezrozumiala. Nalezy jednak
zastanowic sie co robi dokladnie. Instrukcja TEST wykonuje operacje
AND na dwoch argumentach i w oparciu o ten wynik ustawiane sa
odpowiednie flagi.
Nalezalo by wiec przeanalizowac czym jest operacja mnozenia
logicznego AND. Dziala on na argumentach rozmiaru bajt lub slowo
(ale nie na ich zwyklej postaci a postaci binarnej, bo dziala
dokladnie na bitach tych liczb).
Z matematyki wiemy ze 0 AND 0 = 0 ; 0 AND 1 =0 i 1 AND 0 = 0 a 1
AND 1 = 1 a wiec operacja daje wynik jeden wtedy i tylko wtedy gdy
oba bity rowne sa jeden.
Wezmy teraz TEST EAX, EAX. Zalozmy ze EAX=0 czyli 00000000 AND
00000000 = 00000000 czyli na kazdej pozycji bedzie 0 i wtedy
ustawiana jest flaga zerowa Z. Natomiast przy kazdej innej wartosci
np. 00000011 AND 00000011 da nam 00000011 i wtedy jezeli
gdziekolwiek na dowolnej pozycji wystapia w obu argumentach 1 to
flaga Z nie jest ustawiana.
Daje nam to mozliwosc sprawdzenia czy np. EAX jest 0 czy jakas inna
wartoscia, gdzy tylko porownanie dwoch TYCH SAMYCH liczb o wartosci
0 da nam 0 i ustawi flage. Operacja AND na kazdych dwoch TAKICH
SAMYCH roznych od zera nie ustawi flagi zerowej bo zawsze gdzies
bedzie 1 w bitach.
Dlatego tez w programach czesto spotykane instrukcje TEST EAX,EAX a
pozniej JZ adres maja calekiem logiczne znaczenie bo skok nastapi
tylko w przypadku EAX=0. Nie nalezy wiec sugerowac sie domyslnym
znaczeniem instrukcji prownania EAX z EAX :-)
___________________________________________________________________
by, by...-:)
GustawKit via Mandylion
|