A KURS03



#Start Prev Next Contents

Jak pisac programy w jezyku asembler?
Czesc 3 - Podstawowe instrukcje, czyli poznajemy dialekt procesora.

Poznalismy juz rejestry, omowilismy pamiec. Pora zaczac na nich
operowac. Zanim zaczniemy, prosze Was o to, abyscie tej listy tez NIE
uczyli sie na pamiec. Instrukcji jest duzo, a proba zrozumienia ich
wszystkich na raz moze spowodowac niezly chaos. Co najwyzej
przejrzyjcie ta liste kilka razy, aby wiedziec mniej-wiecej, co kazda
instrukcja robi.
Instrukcje procesora mozna podzielic na kilka grup:
* instrukcje przemieszczania danych
* instrukcje arytmetyki binarnej
* instrukcje arytmetyki dziesietnej
* instrukcje logiczne
* operacje na bitach i bajtach
* instrukcje przekazujace kontrole innej czesci programu (sterujace
wykonywaniem programu)
* instrukcje operujace na lancuchach znakow
* instrukcje kontroli flag
* instrukcje rejestrow segmentowych
* inne

Zacznijmy je po kolei omawiac (nie omowie wszystkich).
1. instrukcje przemieszczania danych.
Tutaj zaliczymy juz wielokrotnie uzywane MOV oraz kilka innych:
XCHG , PUSH i POP.
2. arytmetyka binarna.
add do_czego,co - dodaj
sub od_czego,co - odejmij
inc cos / dec cos - zwieksz/zmniejsz cos o 1
cmp co, z_czym - porownaj. Wykonuje dzialanie odejmowania "co
minus z_czym", ale nie zachowuje wyniku, tylko ustawia flagi.
Wynikiem moze byc ustawienie lub wyzerowanie jednej lub wiecej
flag - zaznaczenie wystapienia jednego z warunkow. Glowne warunki
to:
+ A - above - "ponad" (dla liczb traktowanych jako liczby bez
znaku): "co > z_czym"
(przeskocz przyklad uzycia warunku A)
cmp al,bl
ja al_wieksze_od_bl ; ja - jump if above
+ B - below - "ponizej" (bez znaku): co < z_czym
+ G - greater - "wiecej niz" (ze znakiem): co > z_czym
+ L - lower - "mniej niz" (ze znakiem): co < z_czym
+ O - overflow - przepelnienie (ze znakiem, np. przebicie
32767 w gore) ostatniej operacji. Niekoniecznie uzywane przy
cmp.
+ C - carry - przepelnienie (bez znaku, czyli przebicie np.
65535 w gore)
(przeskocz przyklad uzycia warunku C)
add al,bl
jc blad_przepelnienia ; jc - jump if carry
+ E lub Z - equal (rowny) lub zero. Te 2 warunki sa
rownowazne.
(przeskocz przyklady uzycia warunkow rownosci)
cmp ax,cx
je ax_rowne_cx
...
sub bx,dx
jz bx_rowne_dx
+ NE/NZ - przeciwienstwo poprzedniego: not equal/not zero.
+ NA - not above, czyli "nie ponad" - mniejsze lub rowne (ale
dla liczb bez znaku)
+ NB - not below, czyli "nie ponizej" - wieksze lub rowne (dla
liczb bez znaku)
+ NG - not greater, czyli "nie wiecej" - mniejsze lub rowne
(ale dla liczb ze znakiem)
+ NL - not lower, czyli "nie mniej" - wieksze lub rowne (dla
liczb ze znakiem)
+ NC - no carry
+ AE/BE - above or equal ("ponad lub rowne"), below or equal
("ponizej lub rowne")
+ NO - no overflow
3. arytmetyka dziesietna
+ NEG - zmienia znak.
+ MUL, IMUL - mnozenie, mnozenie ze znakiem (czyli uwzglednia
liczby ujemne)
(przeskocz przyklady instrukcji mnozenia)
mul cl ; AX = AL*CL
mul bx ; DX:AX = AX*BX
mul esi ; EDX:EAX = EAX*ESI

imul eax ; EDX:EAX = EAX*EAX
imul ebx,ecx,2 ; EBX = ECX*2
imul ebx,ecx ; EBX = EBX*ECX
imul si,5 ; SI = SI*5
+ DIV, IDIV - dzielenie, dzielenie ze znakiem.
(przeskocz przyklady instrukcji dzielenia)
div cl ; AL = (AX div CL), AH = (AX mod CL)
div bx ; AX = (DX:AX div BX),
; DX = (DX:AX mod BX)
div edi ; EAX = (EDX:EAX div EDI),
; EDX = (EDX:EAX mod EDI)
4. Instrukcje bitowe (logiczne). AND, OR, XOR, NOT, TEST. Instrukcja
TEST dziala tak samo jak AND z tym, ze nie zachowuje nigdzie
wyniku, tylko ustawia flagi. Po krotce wytlumacze te instrukcje:
(przeskocz dzialanie instrukcji logicznych)
0 AND 0 = 0 0 OR 0 = 0 0 XOR 0 = 0
0 AND 1 = 0 0 OR 1 = 1 0 XOR 1 = 1
1 AND 0 = 0 1 OR 0 = 1 1 XOR 0 = 1
1 AND 1 = 1 1 OR 1 = 1 1 XOR 1 = 0
NOT 0 = 1
NOT 1 = 0
Przyklady zastosowania:
(przeskocz przyklady instrukcji logicznych)
and ax,1 ; wyzeruje wszystkie bity z
; wyjatkiem bitu numer 0.
or ebx,1111b ; ustawia (wlacza) 4 dolne bity.
; Reszta bez zmian.
xor cx,cx ; CX = 0
not dh ; DH ma 0 tam, gdzie mial 1
; i na odwrot
5. Instrukcje przesuniecia bitow.
1. SAL, SHL - shift left.
bit7 = bit6, bit6 = bit5, ... , bit1 = bit0, bit0 = 0.
2. SHR - shift logical right
bit0 = bit1, bit1 = bit2, ... , bit6 = bit7, bit7 = 0
3. SAR - shift arithmetic right
bit0 = bit1, bit1 = bit2, ... , bit6 = bit7, bit7 = bit7
(bit znaku zachowany!)
Najstarszy bit w rejestrze nazywa sie czasem wlasnie bitem
znaku.
4. ROL - rotate left
bit7 = bit6, ... , bit1 = bit0, bit0 = stary bit7
5. RCL - rotate through carry left
carry flag CF = bit7, bit7 = bit6, ... , bit1 = bit0, bit0 =
stara CF
6. ROR - rotate right
bit0 = bit1, ... , bit6 = bit7, bit7 = stary bit0
7. RCR - rotate through carry right
CF = bit0, bit0 = bit1, ... , bit6 = bit7, bit7 = stara CF
Przy uzyciu SHL mozna przeprowadzac szybkie mnozenie, a dzieki
SHR - szybkie dzielenie. Np. SHL AX,1 jest rownowazne
przemnozeniu AX przez 2, SHL AX,5 - przez 2^5 = 32. SHR BX,4
dzieli bx przez 16.
6. Instrukcje sterujace wykonywaniem programu.
+ Skoki warunkowe (patrz: warunki powyzej): JA=JNBE, JAE=JNB,
JNA=JBE, JNAE=JB , JG=JNLE (jump if greater - dla liczb ze
znakiem) = jump if not lower or equal, JNG=JLE, JGE=JNL,
JNGE=JL, JO, JNO, JC, JNC, JS (jump if sign czyli bit7
wyniku jest rowny 1), JNS, JP=JPE (jump if parity equal =
liczba bitow rownych jeden jest parzysta), JNP=JPO.
+ Skoki bezwarunkowe: JMP, JMP SHORT, JMP FAR
+ Uruchomienia procedur: CALL [NEAR/FAR]
+ Powrot z procedury: RET/RETF.
+ Przerwania: INT, INTO (wywoluje przerwanie INT4 w razie
przepelnienia), BOUND (int 5)
+ Instrukcje petli: LOOP. Skladnia: "LOOP gdzies". Jesli CX
jest rozny od 0, to skacz do "gdzies".
7. Operacje na lancuchach znakow.
1. LODS[B/W/D] - Load Byte/Word/Dword
MOV AL/AX/EAX , DS:[SI]
ADD SI,1/2/4 ; ADD, gdy flaga kierunku DF = 0, SUB gdy DF =
1
2. STOS[B/W/D] - Store Byte/Word/Dword
MOV ES:[DI], AL/AX/EAX
ADD DI,1/2/4 ; ADD/SUB jak wyzej
3. MOVS[B/W/D] - Move Byte/Word/Dword
MOV ES:[DI], DS:[SI] ; to nie jest instrukcja!
ADD DI,1/2/4 ; ADD/SUB jak wyzej
ADD SI,1/2/4
4. CMPS[B/W/D] - Compare Byte/Word/Dword
CMP DS:[SI], ES:[DI] ; to nie jest instrukcja!
ADD SI,1/2/4 ; ADD/SUB jak wyzej
ADD DI,1/2/4
5. SCAS[B/W/D] - Scan Byte/Word/Dword
skanuje lancuch bajtow/slow/podwojnych slow pod ES:[DI] w
poszukiwaniu, czy jest tam wartosc wskazana przez AL/AX/EAX
Do kazdej z powyzszych instrukcji mozna z przodu dodac
przedrostek REP (repeat), co spowoduje, ze bedzie ona wykonywana,
az CX stanie sie zerem, lub REPE/REPZ lub REPNE/REPNZ co
spowoduje, ze bedzie ona wykonywana, dopoty CX nie jest zerem i
jednoczesnie ZF (zero flag) =1 lub =0, odpowiednio.
8. Instrukcje wejscia/wyjscia do portow.
+ IN
IN AL, port/DX.
Pobierz z portu bajt i wloz do AL. Jesli numer portu jest
mniejszy lub rowny 255, mozna go podac bezposrednio. Jesli
wiekszy - trzeba uzyc DX.
IN AX, port/DX
Jest rownowazne:
IN AL, port/DX
IN AH, port+1/DX+1
IN EAX, port/DX - pobierz 4 bajty - pierwszy z "port" do AL,
drugi - z "port+1" do AH, trzeci - z "port+2" do bitow 23-16
EAX, czwarty - z "port+3" do bitow 31-24 EAX.
+ OUT
OUT port/DX, AL/AX/EAX.
Uwagi jak przy instrukcji IN.
9. Instrukcje flag
+ STC/CLC - set carry / clear carry. Do flagi CF wstaw 1 lub
0, odpowiednio.
+ STD/CLD. Ustaw DF = 1, DF = 0, odpowiednio.
+ STI/CLI. Interrupt Flag IF := 1, IF := 0, odpowiednio. Gdy
IF=0, przerwania sprzetowe sa blokowane.
+ Przenoszenie flag
PUSHF / PUSHFD - umiesc flagi na stosie (16 i 32 bity flag,
odpowiednio)
POPF / POPFD - zdejmij flagi ze stosu (16/32bity flag)
SAHF / LAHF - zapisz AH w pierwszych 8 bitach flag / zapisz
pierwsze 8 bitow flag w AH.
10. Instrukcja LEA - Load Effective Address.
Wykonanie:
lea rej, [pamiec]
jest rownowazne:
(przeskocz pseudo-kod LEA)
mov rej, offset pamiec ; TASM
mov rej, pamiec ; NASM/FASM
Po co wiec osobna instrukcja? Otoz, LEA przydaje sie w wielu
sytuacjach do obliczania zlozonych adresow. Kilka przykladow:
1. Jak w 1 instrukcji sprawic, ze EAX = EBP-12 ?
Odpowiedz: lea eax, [ebp-12]
2. Niech EBX wskazuje na tablice o 20 elementach o rozmiarze 8
kazdy. Jak do ECX zapisac adres 11-tego elementu, a do EDX
elementu o numerze EDI?
Odpowiedz: lea ecx, [ebx + 11*8 ] oraz lea edx,[ebx+edi*8]
3. Jak w 1 instrukcji sprawic, ze ESI = EAX*9?
Odpowiedz: lea esi, [eax + eax*8 ]

Pominalem mniej wazne instrukcje operujace na rejestrach segmentowych
i klika innych instrukcji. Te, ktore tu podalem, wystarczaja
absolutnie na napisanie wiekszosci programow, ktore mozna zrobic.
Wszystkie informacje przedstawione w tej czesci pochodza z tego
samego zrodla: podreczniki Intela i podreczniki AMD

Byle glupiec potrafi napisac kod, ktory zrozumie komputer. Dobry
programista pisze taki kod, ktory zrozumie czlowiek.

Poprzednia czesc kursu (Alt+3)
Kolejna czesc kursu (Alt+4)
Spis tresci off-line (Alt+1)
Spis tresci on-line (Alt+2)
Ulatwienia dla niepelnosprawnych (Alt+0)
________________________________________________________________

Cwiczenia:

1. Zapisz instrukcje: do rejestru AX dodaj 5, o rejestru SI odejmij
178.
2. Nie uzywajac cyfry jeden napisz jedna instrukcje, ktora zmniejszy
rejestr DX o jeden.
3. Przemnoz wartosc rejestru EDI przez 2 na przynajmniej dwa rozne
sposoby po jednej instrukcji. Postaraj sie nie uzywac instrukcji
(I)MUL.
4. W jednej instrukcji podziel wartosc rejestru BP przez 8.
5. Nie uzywajac instrukcji MOV spraw, by DX mial wartosc 0 (na
przynajmniej 3 sposoby, kazdy po jednej instrukcji).
6. Nie uzywajac instrukcji przesuwania bitow SH* ani mnozenia *MUL
przemnoz EBX przez 8. Mozesz uzyc wiecej niz 1 instrukcji.
7. W dwoch instrukcjach spraw, by EDI rownal sie 7*ECX. Postaraj sie
nie uzywac instrukcji (I)MUL.


Wyszukiwarka

Podobne podstrony:
a kurs03
DOS A KURS03
KURS03
A KURS03
kurs0304
A KURS03

więcej podobnych podstron