[ Pobierz całość w formacie PDF ]
Podobne instrukcje istnieją także dla liczb i rejestrów zmiennoprzecinkowych: FCMOV*.
138 Bogdan Drozdowski
2009-02-25 Język asembler dla każdego Bogdan Drozdowski
Pętle.
(przeskocz pętle)
Z pętlami jest trochę gorzej, gdyż jest ich więcej rodzajów.
Zacznijmy od pętli o znanej z góry ilości przejść (powtórzeń, iteracji), czy pętli typu
for (wyrażenia początkowe; warunek wykonywania; wyrażenie końcowe)
Na przykład:
(przeskocz przykład pętli for)
for (i=1; i
{
j=j+i;
}
zostałoby przetłumaczone na:
(przeskocz tłumaczenie tego przykładu)
mov ecx, 1 ; ECX to zmienna I. i=1
petla_for:
cmp ecx, 10
jae koniec_petli ; wychodzimy, gdy i >= 10
add eax, ecx ; EAX to zmienna J. j=j+i
add ecx, 1 ; i=i+1
jmp short petla_for
koniec_petli:
Jeśli warunkiem zakończenia pętli jest to, że pewna zmienna osiągnie zero, można stosować instrukcję LOOP.
Przykład:
(przeskocz drugą pętlę for)
for (i=10; i>0; i--)
{
j=j+i;
}
może zostać przetłumaczony na 2 sposoby:
(przeskocz sposoby tłumaczenia)
; sposób 1:
mov ecx, 10 ; ECX to zmienna I. i=1
petla_for:
cmp ecx, 0 ; lub: test ecx, ecx
jbe koniec_petli ; wychodzimy, gdy i
add eax, ecx ; EAX to zmienna J. j=j+i
sub ecx, 1 ; i=i-1
jmp short petla_for
koniec_petli:
Bogdan Drozdowski 139
Bogdan Drozdowski Język asembler dla każdego 2009-02-25
; sposób 2:
mov ecx, 10 ; ECX to zmienna I. i=1
petla_for:
add eax, ecx ; EAX to zmienna J. j=j+i
loop petla_for ; zmniejsz ECX o 1 i jeśli różny od
; zera, skocz do: petla_for
Pamiętajmy jednak, że instrukcja LOOP działa tylko na rejestrze (E)CX, więc jeśli chcemy mieć kilka
zagnieżdżonych pętli, to przed każdą z nich (rozpoczynającą się zmianą rejestru ECX) musimy zachować ten
rejestr (np. na stosie), a po zakończeniu pętli musimy przywrócić jego poprzednią wartość.
Sprawa z pętlami o nieznanej ilości powtórzeń nie jest o wiele trudniejsza. Pętla typu for jest całkowicie
równoważna pętli while. Właśnie z tego skorzystamy, a kod niewiele będzie się różnić budową od
poprzedniego przykładu.
Powiedzmy, że mamy taką pętlę:
(przeskocz ten przykład)
for (i=100; i+1
{
j=j+i+4;
}
Możemy ją zastąpić równoważną konstrukcją:
(przeskocz zamianę for na while)
i=100;
while (i+1
{
j=j+i+4;
i=1+2;
}
Otrzymujemy kod:
(przeskocz tłumaczenie while)
mov ecx, 100 ; ECX to zmienna I. i=100
nasza_petla:
mov ebx, ecx
add ebx, 1 ; EBX = i+1
cmp ebx, [n] ; sprawdzamy, czy i+1
ja koniec_while ; wychodzimy, gdy i+1 > n
add eax, ecx ; EAX to zmienna J. j=j+i
add eax, 4 ; j=j+i+4
add ecx, 2 ; i=i+2
jmp short nasza_petla
koniec_while:
Ostatni rodzaj pętli to pętle typu do-while (repeat...until). Taka pętla różni się tym od poprzedniczek, że
warunek jest sprawdzany po wykonaniu kodu pętli (czyli taka pętla zawsze będzie wykonana co najmniej
raz). Daje to pewne możliwości optymalizacji kodu.
Popatrzmy na taki przykład:
(przeskocz przykład do-while)
do
140 Bogdan Drozdowski
2009-02-25 Język asembler dla każdego Bogdan Drozdowski
{
i=i+1;
j=j-1;
} while ((i 1));
Warunek wyjścia to: i >= n LUB j
A teraz popatrzcie, co można z tym zrobić:
(przeskocz tłumaczenie do-while)
petla_do:
add ecx, 1 ; ECX to zmienna I. i=i+1
add edx, 1 ; EDX to zmienna J. j=j+1
cmp ecx, [n]
jae koniec ; i >= n jest jednym z warunków
; wyjścia. Drugiego nie musimy
; sprawdzać, bo wynik i tak
; będzie prawdą
cmp edx, 1
jbe koniec ; j
jmp petla_do
koniec:
Można przepisać to w lepszy sposób:
(przeskocz lepszy sposób)
petla_do:
add ecx, 1 ; ECX to zmienna I. i=i+1
add edx, 1 ; EDX to zmienna J. j=j+1
cmp ecx, [n]
jae koniec ; i >= n jest jednym z warunków
; wyjścia. Drugiego nie musimy
; sprawdzać, bo wynik i tak
; będzie prawdą
; jeśli nadal tutaj jesteśmy,
; to z pewnością i
cmp edx, 1
ja petla_do ; j
; wyjścia. Jeśli j > 1,
; to kontynuuj wykonywanie pętli.
; Jeśli j
; opuszczamy pętlę:
koniec:
Jeśli warunek kontynuacji lub wyjścia z pętli jest wyrażeniem złożonym, to:
" jeśli składa się z alternatyw (działań typu OR, ||), to na pierwszym miejscu sprawdzajcie te warunki,
które mają największą szansę być prawdziwe. Oszczędzicie w ten sposób czasu na bezsensowne
sprawdzanie reszty warunków (wynik i tak będzie prawdą).
" jeśli składa się z koniunkcji (działań typu AND, &&), to na pierwszym miejscu sprawdzajcie te
warunki, które mają największą szansę być fałszywe. Wynik całości i tak będzie fałszem.
Przykłady:
[ Pobierz całość w formacie PDF ]