ROZDZIAŁ PIĘTNASTY CIĄGI ZNAKÓW I ZESTAWY ZNAKÓW, INFORMATYKA, „THE ART OF ASSEMBLY LANGUAGE” [PL]
[ Pobierz całość w formacie PDF ]
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
WYŁĄCZNOŚĆ DO PUBLIKOWANIA TEGO TŁUMACZENIA
POSIADA
RAG
„THE ART OF ASSEMBLY LANGUAGE”
tłumaczone by KREMIK
Konsultacje naukowe: NEKRO
wankenob@priv5.onet.pl
nekro@pf.pl
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
ROZDZIAŁ PIĘTNASTY:
CIĄGI ZNAKÓW I ZESTAWY ZNAKÓW
Ciąg jest zbiorem obiektów przechowywanych w przylegających do siebie komórkach pamięci. Ciągi
są zazwyczaj tablicami bajtów, słów lub (w 80386 i późniejszych procesorach) podwójnych słów Procesory z
rodziny 80x86 wspierają kilka instrukcji specjalnie zaprojektowanych do kopiowania ciągów. Rozdział ten
zgłębi kilka zastosowań tych instrukcji ciągów.
8088, 8086, 80186 i 80286 mogą przetwarzać dwa typy ciągów: ciągi bajtów i ciągi słów. 80386 i
późniejsze procesory działają również na ciągach podwójnych słów. Mogą one przenosić ciągi, porównywać
ciągi, szukać określonej wartości wewnątrz ciągu, inicjalizować ciąg stałą wartością i inne elementarne operacje
na ciągach. Instrukcje ciągów 80x86 również są użyteczne dla manipulowania tablicami, tabelami i rekordami.
Możemy łatwo przypisać lub porównać takie struktury danych używając instrukcji ciągów. Używając tych
instrukcji możemy znacznie przyspieszyć kod działający na tablicach.
15.0 WSTĘP
Rozdział ten przedstawia przegląd operacji instrukcji ciągów 80x86. Potem omawia jak przetwarzać
ciągi znaków używając tych instrukcji . W końcu, omawia instrukcje ciągów dostępne w Bibliotece
Standardowej UCR. Poniższe sekcje, które mają prefiks „ •” są niezbędne. Te sekcje z „⊗” omawiają
zaawansowane tematy, które możemy odłożyć na później.
• Instrukcje ciągów 80x86
• Ciągi znaków
• Funkcje ciągów znaków
• Funkcje ciągów w Bibliotece Standardowej UCR
⊗ Zastosowanie instrukcji ciągów w innych typach danych
15.1 INSTRUKCJE CIĄGÓW 80X86
Wszyscy członkowie rodziny 80x86 wspierają pięć różnych instrukcji ciągów: movs, cmps, scas, lods i
stos. Są one ciągami elementarnymi ponieważ możemy zbudować większość innych operacji ciągów z tych
pięciu instrukcji. Jak używać tych pięciu instrukcji , jest tematem następnych kilku sekcji.
15.1.1 JAK DZIAŁAJĄ INSTUKCJE CIĄGÓW
Instrukcje ciągów działają na blokach (tablicach o liniowej ciągłości) pamięci. Na przykład, instrukcja
movs przesuwa sekwencję bajtów z jednej lokacji pamięci do innej. Instrukcja cmps porównuj dwa bloki w
pamięci. Instrukcja scas przeszukuje blok pamięci pod katem określonej wartości. Te instrukcje ciągów często
wymagają trzech operandów, adresu bloku przeznaczenia, adresu bloku źródłowego i (opcjonalnie) elementu
zliczającego. Na przykład, kiedy używamy instrukcji movs do kopiowania ciągu, potrzebujemy adresu
źródłowego i licznika (liczby elementów ciągu do przesunięcia)
W odróżnieniu od innych instrukcji które działają na pamięci, instrukcje ciągów są instrukcjami
jednobajtowymi, które nie maja żadnych jasnych operandów. Argumenty dla instrukcji ciągów to:
•
Rejestr si (indeks źródła)
•
Rejestr di (indeks przeznaczenia
•
Rejestr cx (licznik)
•
Rejestr ax i
•
Flaga kierunku w rejestrze FLAGS
A przykład jeden wariant instrukcji movs (przenieś ciąg) kopiuje ciąg spod adresu określonego przez
ds:si do adresu określonego przez es:di, o długości cx. Podobnie instrukcja cmps porównuje ciąg wskazywany
przez ds:si o długości cx z ciągiem wskazywanym przez es:di
Nie wszystkie instrukcje mają operand źródłowy i przeznaczenia (tylko movs i cmps) . Na przykład
instrukcja scas (przeszukaj ciąg) porównuje wartość w akumulatorze z wartością w pamięci. Pomimo różnic,
instrukcje ciągów wszystkie mają jedną rzecz wspólną – używanie ich wymaga abyśmy działali na dwóch
segmentach, segmencie danych i dodatkowym segmencie.
15.1.2 PRZDROSTKI REP / REPE / REPZ I REPNZ / REPNE
Instrukcje ciągów same z siebie nie działają na ciągach danych. Instrukcja movs na przykład będzie
przesuwała pojedynczy bajt, słowo lub podwójne słowo. Kiedy będzie się wykonywała, instrukcja movs
zignoruje wartość z rejestru cx. Przedrostki powtórki mówią 80x86 aby wykonał wielobajtową operację na
ciągach. Składnia dla przedrostków powtórki to:
Pole:
Etykieta
repeat
mnemonik
argument
;komentarz
Dla MOVS:
rep
movs
{argumenty}
Dla CMPS:
repe
cmps
{argumenty}
repz
cmps
{argumenty}
repne
cmps
{argumenty}
repnz
cmps
{argumenty}
Dla SCAS:
repe
scas
{argumenty}
repz
scas
{argumenty}
repne
scas
{argumenty}
repnz
scas
{argumenty}
Dla STOS:
rep
stos
{argumenty}
Zazwyczaj nie będziemy używali przedrostków powtórzenia z instrukcją lods.
Jak widzimy, obecność przedrostków powtórzenia wprowadza nowe pole w lini źródłowej – pole
przedrostka powtórzenia. Pole to pojawia si tylko w lini źródłowej zawierającej instrukcje ciągów. W naszym
pliku źródłowym:
•
etykieta pola powinna zawsze zaczynać się w kolumnie jeden
•
pole powtórzenia powinno zaczynać się od pierwszego miejsca tabulacji , i
•
pole mnemonika powinno zaczynać się od drugiego miejsca tabulacji
Kiedy określamy przedrostek powtórzenia przed instrukcją ciągu, instrukcja ta jest powtarzana cx razy.
Bez tego przedrostka, instrukcja działa tylko na pojedynczym bajcie, słowie lub podwójnym słowie. Możemy
użyć przedrostka powtórzenia do przetwarzania całego ciągu pojedyncza instrukcją. Możemy użyć instrukcji
ciągów, bez przedrostka powtórzenia, jako elementarnych operacji na ciągach do zsyntetyzowania bardziej
złożonych operacji na ciągach.
Pole operacji jest opcjonalne. Jeśli jest obecne, MASM po prostu używa go do określenia rozmiaru
ciągu na jakim będzie działał. Jeśli pole operandu jest nazwą zmiennej bajtowej, instrukcja ciągu będzie działała
na bajtach. Jeśli argument jest adresem słowa, instrukcja działa na słowie. Podobnie z podwójnym słowem. Jeśli
pole argumentu nie jest obecne, musimy dołączyć „B”, „W” lub „D” na końcu instrukcji ciągu dla oznaczenia
rozmiaru np. movsb, movsw lub movsd.
15.1.3 FLAGA KIERUNKU
Oprócz rejestrów si, di si i ax, jednym z rejestrów sterujących instrukcjami ciągów 80x86 jest rejestr
flag. Ściśle, flaga kierunku w rejestrze sterującym flag, jeśli CPU przetwarza ciągi.
Jeśli flaga kierunku jest wyzerowana, CPU zwiększa si i di po operacji na każdym elemencie ciągu. Na
przykład, jeśli flaga kierunku jest wyzerowana, wtedy wykonanie movs przeniesie bajt, słowo lub podwójne
słowo spod ds:si do es:di i zwiększy si i di o jeden, dwa lub cztery. Kiedy wyspecyfikujemy przedrostek rep
przed tą instrukcją, CPU zwiększy si i di dla każdego elementu w ciągu. Po zakończeniu, rejestry si i di będą
wskazywały pierwszą pozycję poza ciągiem.
Jeśli flag kierunku jest ustawiona, wtedy 80x86 zmniejsza si i di po przetworzeniu każdego elementu
ciągu. Po powtórzeniu operacji na ciągu, rejestry si i di będą wskazywały na pierwszy bajt lub słowo przed
ciągiem, jeśli flaga kierunku była ustawiona.
Flaga kierunku może być ustawiona lub zerowana przy użyciu instrukcji cld (zeruj flagę kierunku) i std
(ustaw flagę kierunku). Kiedy używamy tych instrukcji wewnątrz procedury, zapamiętajmy, że modyfikują one
stan maszynowy. Dlatego też musimy zachować flagę kierunku podczas wykonywania tej procedury. Poniższy
przykład wskazuje rodzaje problemów jakie możemy napotkać:
StringStuff:
cld
<jakieś operacje>
call Str2
<jakiś operacje na ciągach wymagające D=0>
-
-
-
Str2
proc
near
Std
<jakieś operacje na ciągach>
ret
Str2
endp
Kod ten nie pracuje właściwie. Kod wywołujący zakłada, że flaga kierunku jest wyzerowana po
powrocie Str2.Jednakże, nie jest to prawda. Dlatego też, operacje na ciągach wykonywane po wywołaniu Str2
nie funkcjonują poprawnie.
Jest parę sposobów zadziałania z tym problemem. Pierwszy, i prawdopodobnie najbardziej oczywisty,
to zawsze wprowadzać instrukcje cld i std bezpośrednio przed wykonywaniem instrukcji na ciągach. Inną
alternatywą jest zachowanie i przywrócenie flagi kierunku używając instrukcji pushf i popf. Po zastosowaniu
tych dwóch technik powyższy kod będzie wyglądał jak następuje:
Zawsze wstawimy cld i std przed instrukcje ciągów:
StringStuff:
cld
<jakieś operacje>
call
Str2
cld
<operacje wymagające D = 0>
-
-
-
Str2
proc
near
std
<jakieś operacje na ciągach>
ret
Str2
endp
Zachowanie i przywrócenie rejestr flag:
StringStuff:
cld
<jakieś operacje>
call Str2
<operacje wymagające D = 0>
-
-
-
Str2
proc
near
pushf
std
<jakieś operacje>
popf
ret
Str2
endp
Jeśli użyjemy instrukcji pushf i popf do zachowania i przywrócenia rejestru flag, zapamiętajmy, że
zachowujmy i przywracamy wszystkie flagi. Dlatego też, taki podprogram nie może zwracać żadnych informacji
we flagach. Na przykład, nie będziemy mogli zwrócić warunku błędu we fladze przeniesienia jeśli użyliśmy
pushf i popf.
15.1.4 INSTRUKCJA MOVS
Instrukcja movs przybiera cztery podstawowe formy. Movs przenosi bajty, słowa lub podwójne słowa,
movsb przesuwa ciąg bajtowy, movsw przenosi ciąg słów a movsd przenosi ciąg podwójnego słowa ( na 80386
lub późniejszych procesorach). Te cztery instrukcje używają następującej składni:
{REP} MOVSB
{REP} MOVSW
{REP} MOVSD
;dostępna na 80386 lub późniejszych procesorach
{REP} MOVS Przeznaczenie, Źródło
Instrukcja movsb (przenieś ciąg bajtowy) pobiera bajt spod adresu ds.:si, przechowuje go pod adresem
es:di, a potem zwiększa lub zmniejsza rejestry si i di o jeden. Jeśli jest obecny przedrostek rep, CPU sprawdza cx
aby zobaczyć czy zawiera zero. Jeśli nie, wtedy przenosi bajt z ds.:si do es:di i zmniejsza rejestr cx. Ten proces
będzie się powtarzał dopóki cx nie będzie zawierał zero.
Instrukcja movsw (przenieś ciąg słów) pobiera słowo spod adresu ds.:si, przechowuje go pod adresem
es:di a potem zwiększa lub zmniejsza si i di o dwa. Jeśli jest przedrostek rep, wtedy CPU powtarza tą procedurę
tak długo jak jest to określone w cx.
Instrukcja movsd działa w podobny sposób na podwójnych słowach. Zwiększa lub zmniejsza si i di o
cztery dla każdego przesunięcia danych.
MASM automatycznie wylicza rozmiar instrukcji movs poprzez „rzut oka” na rozmiar określonych
argumentów. Jeśli zdefiniujemy dwa argumenty dyrektywą byte (lub porównywalną), wtedy MASM wygeneruje
instrukcję movsb. Jeśli zadeklarujemy dwie etykiety przez word (lub porównywalne), MASM wygeneruje
instrukcję movsw. Jeśli zadeklarujemy dwie etykiety jako dword, MASM wygeneruje instrukcję movsd.
Asembler również sprawdzi segmenty argumentów aby zapewnić, że pasują one do aktualnie założonych (przez
dyrektywę assume) rejestrów es i ds. Zawsze powinniśmy używać postaci movsb, movsw i movsd i zapomnieć o
postaci movs.
Chociaż teoretycznie, forma movs wydaje się być eleganckim sposobem manipulowania instrukcjami
przenoszenia ciągów, w praktyce tworzy więcej problemów niż jest to warte. Co więcej ta forma instrukcji
przenoszenia ciągów sugeruje, że movs ma jawne argumenty, kiedy w rzeczywistości rejestry si i di pośrednio
określają argumenty. Z tego powodu zawsze używajmy instrukcji movsb, movsw i movsd. Kiedy używamy
przedrostka rep, instrukcja movsb przeniesie liczę bajtów określoną w rejestrze cx. Poniższy fragment kodu
kopiuje 384 bajty z String1 do String2:
cld
lea
si, String1
lea
di, String2
mov
cx, 384
rep
movsb
-
-
-
String1
byte
384 dup (?)
String2
byte
384 dup (?)
Kod ten oczywiście zakłada, że String1 i String2 są w tym samym segmencie i oba rejestry ds. i es
wskazują ten segment. Jeśli zastąpimy movsb przez movsw, wtedy powyższy kod przeniesie384 słowa (768
bajtów) zamiast 384 bajtów:
cld
lea
si, String1
lea
di, String2
mov
cx, 384
rep
movsw
-
-
-
String1
word 384 dup (?)
String2
word 384 dup (?)
Pamiętamy, że cx zawiera element liczącym nie licznik bajtów. Kiedy używamy instrukcji movsw,
CPU przesuwa liczbę słów określonych w rejestrze.
Jeśli ustawimy flagę kierunku przed wykonaniem instrukcji movsb / movsw / movsd, CPU zmniejszy
rejestry si i di po przeniesieniu każdego elementu ciągu. To znaczy, że si i di muszą wskazywać koniec ich
właściwych ciągów przed wywołaniem instrukcji movsb, movsw lub movsd. Na przykład
std
lea
si, String1+383
lea
di,String2+383
mov
cx, 384
rep
movsb
-
-
-
String1
byte
384 dup (?)
String2
byte
384 dup (?)
Chociaż są chwile kiedy przetwarzanie ciągu od końca do początku jest użyteczne (zobacz opis cmps w
następnej sekcji), generalnie będziemy przetwarzać ciągi w kierunku do przodu ponieważ jest to dużo prostsze
do zrobienia Jest jedna klasa operacji na ciągach gdzie przetwarzanie ciągów w obu kierunkach jest całkowicie
obowiązkowe: przetwarzanie ciągów kiedy blok źródłowy i przeznaczenia zachodzą na siebie. Rozważmy co
zdarzy się w następującym kodzie:
cld
lea
si, String1
lea
di, String2
mov
cx, 384
rep
movsb
-
-
-
String1
byte
?
String2
byte
384 dup (?)
[ Pobierz całość w formacie PDF ]
-
Linki
- Home
- Psych.9 - Psych 9 (2010) BRRip.XviD.x264.NAPiSY PL, sporo filmów do ściągnięcia
- Psych.9 - Psych 9 (2010) BRRip.XviD.NAPiSY PL, sporo filmów do ściągnięcia
- RED - Red (2010) BDRip.XviD.Napisy PL 3, sporo filmów do ściągnięcia
- RED - Red (2010) BDRip.XviD.Napisy PL, sporo filmów do ściągnięcia
- RED - Red (2010) BDRip.XviD.Napisy PL 2, sporo filmów do ściągnięcia
- Rambo-First.Blood.Part.II[1985]DvDrip-aXXo.pl, ● Filmy ●, -Rambo- kolekcja
- Radical 2017 PL, WĘDKARSTWO, Dokumenty wędkarskie PDF i KATALOGI
- Resident Evil Degeneration 2008 napisy PL, napisy do filmow
- Rambo.III[1988]DvDrip-aXXo.pl, ● Filmy ●, -Rambo- kolekcja
- Renault Clio Megane Sagem Tacho -2003, Diagnostyka Samochodowa, Programy, Programy diagnostyczne, EfiChip, TachoCombinedManuals122006, Deutsch
- zanotowane.pl
- doc.pisz.pl
- pdf.pisz.pl
- streamer.htw.pl