ROZDZIAŁ SZÓSTY ZBIÓR INSTRUKCJI PROCESORA 80x86, 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Ł SZÓSTY:
ZBIÓR INSTRUKCJI PROCESORA 80x86
Dotychczas ,tylko trochę omówiliśmy dostępne instrukcje w mikroprocesorze 80x86.Ten rozdział
naprawi tą sytuację. Zauważmy, że ten rozdział jest głównie odniesieniem .Wyjaśnia co każda instrukcja robi,
nie wyjaśnia jak łączą się te instrukcje w programie napisanym w języku asemblera. Reszta tej książki wyjaśnia
jak się to robi.
6.0 WSTĘP
Ten rozdział omawia zbiór instrukcji trybu rzeczywistego 80x86.Podobnie jak w innych językach
programowania, będzie kilka instrukcji, których będziemy używać cały czas ,kilka będziemy używać
okazjonalnie ,a kilku będziemy używać rzadko, jeśli w ogóle. Rozdział ten będzie przedstawiał instrukcje
według klas zamiast według znaczenia. Ponieważ początkujący programiści asemblerowi nie muszą uczyć się
całego zbioru instrukcji żeby pisać sensowne programy asemblerowe ,nie będziemy się musieli uczyć jak każda
instrukcja działa. Następująca lista opisuje instrukcje omawiane w tym rozdziale. Symbol „•” oznacza ważne
instrukcje w każdej grupie. Jeśli nauczymy się tylko tych instrukcji, będziemy mogli napisać każdy program
asemblerowy jaki zechcemy .Jest wiele dodatkowych instrukcji, zwłaszcza w procesorze 80386 i późniejszych
.Te dodatkowe instrukcje czynią programowanie w asemblerze łatwiejszym, ale nie musimy ich znać aby zacząć
pisać programy.
Instrukcje 80x86 mogą być ( z grubsza) podzielone na osiem różnych klas:
1)
Instrukcje przenoszenia danych
•
mov, lea, les, push, pop ,pushf, popf
2)
Konwersja
•
cbw, cwd, xlat
3)
Instrukcje arytmetyczne
•
Add ,inc ,sub ,dec ,cmp ,neg ,mul, imul, div ,idiv
4)
Instrukcje logiczne ,przesunięcia, obrotu i bitowe
•
and, or, xor, not, shl, shr ,rcl ,rcr
5)
Instrukcje I/O
•
in, out
6)
Instrukcje łańcuchowe
•
movs, stos ,lods
7)
Instrukcje sterowania strumieniem danych w programie
•
jmp, call, ret, skoki warunkowe
8)
Instrukcje różne
•
clc, stc, cmc
Następna sekcja omówi wszystkie te instrukcje w tych grupach i jak one działają.
Raz jeden jeszcze w tym tekście nie rekomenduje się używania rozszerzonego zbioru instrukcji
80386.Program,który używa takich instrukcji może nie pracować właściwie na procesorze 80286 lub
wcześniejszych. Używanie tych dodatkowych instrukcji może ograniczyć liczbę maszyn na których nasz kod
będzie działał. Jednak, procesor 80386 zostanie w tym tekście opisany. Możemy bezpiecznie założyć, że
większość systemów będzie zawierać procesor 80386sx lub późniejsze. Ten tekst często używa zbioru instrukcji
80386 w różnych przykładowych programach. Zapamiętajmy, jest to zrobione tylko dla wygody .Nie ma
programu który pojawia się w tym tekście, który nie mógłby być przekodowany przy użyciu tylko instrukcji
asemblerowych CPU 8088.
Słowo porady, szczególnie dla tych, którzy uczą się tylko powyższych instrukcji: jeśli czytasz o zbiorze
instrukcji 80x86,odkryjesz,że pojedyncze instrukcje 80x86 nie są bardzo złożone i mają prostą semantykę.
Jednak jeśli nadejdzie
Rysunek 6.1 :Rejestr flag 80x86
koniec tego rozdziału, możesz odkryć ,że nie masz pojęcia jak ułożyć te proste instrukcje razem w formie
złożonego programu. Nie bój nic, jest to powszechny problem. Późniejsze rozdziały omówią jak sformować
złożony program z tych prostych instrukcji.
Jedna szybka uwaga: ten rozdział wyliczył dużo instrukcji jakie „dostępne są na procesorze 80286 i
późniejszych procesorach”. Faktycznie wiele z tych instrukcji było również dostępnych w mikroprocesorze
80186.Ponieważ tylko kilka systemów PC stosuje mikroprocesor 80186,ten tekst ignoruje ten CPU
6.1 REJESTRY STANU PROCESORA (FLAGI)
Rejestr flag utrzymuje bieżący tryb działania CPU i informuje o jego stanie. Rysunek 6.1 pokazuje
układ rejestru flag.
Znaczniki
przeniesienia, parzystości, zera, znaku i przepełnienia są specjalne ponieważ możemy
testować ich stan (zero lub jeden) setcc i instrukcjami skoków warunkowych (zobacz „Zbiór instrukcji
warunkowych” i „Instrukcje skoków warunkowych”) 80x86 używa tych bitów ,kodów błędu, do podjęcia
decyzji podczas wykonywania programu.
Różne arytmetyczne ,logiczne i inne różne instrukcje wpływają na znacznik przepełnienia
(overflow).Po operacjach arytmetycznych, flaga ta zawiera jeden jeśli wynik nie mieści się w operandzie
przeznaczenia ze znakiem. Na przykład, jeśli próbujemy dodawać 16 bitową liczbę ze znakiem 7FFFh i
0001h,wynik jest zbyt duży więc CPU ustawia flagę przepełnienia. Jeśli wynik operacji arytmetycznej nie
tworzy przepełnienia, wtedy CPU czyści tą flagę.
Ponieważ generalnie operacje logiczne stosują wartości bez znaku, instrukcje logiczne 80x86 po prostu
czyszczą flagę przepełnienia. Inne instrukcje 80x86 opuszczają flagę przepełnienia zawierającą dowolna
wartość.
Instrukcje łańcuchowe 80x86 używają znacznika kierunku (direction flag).Kiedy flaga kierunku jest
wyczyszczona, 80x86 przetwarza elementy łańcucha od adresu niższego do wyższego; kiedy ustawiona CPU
przetwarza łańcuch w kierunku przeciwnym. Zobacz ”Instrukcje Łańcuchowe: po dodatkowe szczegóły.
Znacznik zezwolenia na przerwanie (interrupt enable/disable flag) steruje zdolnością 80x86 do
odpowiedzi na zewnętrzne zdarzenie znane jako prośba o przerwanie. Niektóre programy zawierają pewną
sekwencję instrukcji, których nie wolno przerwać CPU. Flaga zezwolenia na przerwanie włącza lub wyłącza
przerwania gwarantując, że CPU nie przerwie tej krytycznej sekcji kodu.
Znacznik stanu śledzenie (trace flag) włącza lub wyłącza tryb śledzenia. Debuggery (takie jak
CodeView) używają tego bitu do włączania lub wyłączania operacji pojedynczego kroku śledzenia. Kiedy jest
ustawiony, CPU przerywa każdą instrukcję i przekazuje sterowanie do debuggera pozwalając mu na
wykonywanie pojedynczego kroku przez aplikację. Jeśli ten bit jest wyczyszczony ,wtedy 80x86 wykonuje
instrukcje bez przerwania. CPU 80x86 nie dostarcza żadnej instrukcji ,która bezpośrednio manipuluje tą flagą
.Aby ustawić lub wyczyścić tą flagę musimy:
•
Odłożyć flagi na stos 80x86
•
Ściągnąć wartość innego rejestru
•
Ustawić
wartość flagi stanu śledzenia
•
Odłożyć wynik na stos a potem
•
Ściągnąć flagi ze stosu
Jeśli wynik jakiegoś obliczenia jest negatywany,80x86 ustawia znacznik znaku. Możemy przetestować
tę flagę po operacji arytmetycznej dla sprawdzenia ujemnego wyniku. Pamiętamy ,wartość jest ujemna jeśli jej
najbardziej znaczący bit wynosi jeden. Dlatego też operacje na wartościach bez znakowych ustawią flagę znaku
jeśli rezultat ma jedynkę na najbardziej znaczącej pozycji.
Różne instrukcje ustawiają znacznik zera kiedy generują jako wynik zero. Często będziemy używać tej
flagi aby zobaczyć, czy dwie wartości są równe (np. po odjęciu dwóch liczb, są one równe jeśli wynik wynosi
zero).Flaga ta jest również użyteczna po różnych operacjach logicznych aby zobaczyć czy wyspecyfikowany bit
w rejestrze lub pamięci zawiera zero czy jeden.
Znacznik przeniesienia połówkowego wspiera operacje specjalnego systemu dziesiętnego kodowanego
dwójkowo (BCD).Ponieważ większość programów nie stosuje liczb BCD, rzadko będziemy używać tej flagi a i
nawet wtedy nie uzyskamy do niej bezpośrednio dostępu.. CPU 80x86 nie dostarczają żadnej instrukcji, która
pozwalałaby nam bezpośrednio testować, ustawiać i czyścić tą flagę. Tylko instrukcje add, adc, sub, sbb, mul,
imul, div, idiv i BCD manipulują tą flagą.
Znacznik parzystości jest ustawiany według parzystości najmniej znaczących bitów każdej operacji na
danych. Jeśli operacja tworzy parzystą liczbę bitów, CPU ustawia tą flagę. Zeruje tą flagę jeśli operacja
przynosi nieparzystą liczbę bitów. Flaga ta jest użyteczna w pewnych programach komunikacyjnych, jednak
Intel wprowadził go głównie dla kompatybilności ze starszymi mikroprocesorami 8080.
Znacznik przeniesienia ma kilka zadań. Po pierwsze oznacza przepełnienie bez znakowe (podobnie jak
znacznik przepełnienia wykrywa przepełnienie znakowe).Możemy go również użyć podczas operacji
arytmetycznych i logicznych o dużej dokładności. Pewne bity testowe, ustawiania, zerowania i inwersji w
80386 bezpośrednio wpływają na tą flagę. W końcu, ponieważ możemy łatwo zerować, ustawiać ,odwracać i
testować ją, jest użyteczna dla różnych operacji boolowskich. Flaga przeniesienia ma wiele zadań i znajomość
kiedy ją użyć i w jakim celu może wprowadzić w zakłopotanie początkującego programistę asemblerowego. Na
szczęście, dla większości danych instrukcji, flaga przeniesienia jest zerowana.
Używanie tych znaczników stanie się łatwe i oczywiste w przyszłych sekcjach i rozdziałach. Ta sekcja
jest głównie formalnym wprowadzeniem do pojedynczych flag w rejestrze zamiast próba dokładnego
wyjaśnienia funkcjonowania każdej z flag.
6.2 KODOWANIE INSTRUKCJI
80x86 używa kodowania binarnego dla każdej operacji maszynowej. Podczas gdy jest ważne mieć
ogólne pojęcie jak 80x86 koduje instrukcje, nie jest tak ważne wprowadzanie do pamięci kodowania dla
wszystkich instrukcji w zbiorze instrukcji. Gdybyśmy pisali asembler lub disasembler (debugger) musielibyśmy
koniecznie znać dokładnie kodowanie .Jednak dla ogólnych programów asemblerowych nie musimy znać
dokładnego kodowania.
Ponieważ stajemy się bardziej doświadczeni w asemblerze prawdopodobnie chcielibyśmy studiować
kodowania zbioru instrukcji 80x86.Oczywiście powinniśmy być zaznajomieni z takimi terminami jak opcod
,bajt mod-reg-r/m., wartość przemieszczenia ,i innymi. Chociaż nie musimy zapamiętywać parametrów dla
każdej instrukcji, jest zawsze dobrym pomysłem znać długość i czas cyklu dla instrukcji używanych regularnie
ponieważ pomoże to nam pisać lepsze programy. Rozdział Trzeci i Rozdział Czwarty dostarczyły szczegółów
odnośnie kodowania instrukcji dla różnych instrukcji (80x86 i x86);takie omówienie było ważne ponieważ
musimy zrozumieć jak CPU koduje i wykonuje instrukcje. ten rozdział nie zajmuje się takimi szczegółami Ten
rozdział przedstawia wysokopoziomowy obraz każdej instrukcji i zakłada, że nie interesuje nas jak maszyna
traktuje bity w pamięci. Dla tych kilku razy, kiedy będziemy musieli poznać kodowanie binarne dla
poszczególnych instrukcji, kompletny listing kodowania instrukcji zawiera Appendix D.
6.3 INSTRUKCJE PRZENOSZENIA DANYCH
Instrukcje przenoszenia danych kopiują wartości z jednej lokacji do innej. Te instrukcje to
mov,xchg,lds,lea,les,lfs,lgs,lss,push,pusha,pushad,pushf,pushfd,pop,popa,popad,popf,popfd,lahf i sahf
6.3.1 INSTRUKCJA MOV
Instrukcja mov przybiera kilka różnych form:
mov
reg, reg
mov
mem ,reg
mov
reg, mem
mov
mem, dana bezpośrednia
mov
reg, dana bezpośrednia
mov
ax/al., mem
mov
mem, ax/al.
mov
segreg, mem
16
mov
segreg, reg
16
mov
mem
16
, segreg
mov
reg
16
,segreg
Ostatni rozdział omawiał instrukcję mov szczegółowo, więc tylko trochę komentarzy godnych uwagi
.Po pierwsze, są to warianty instrukcji mov które są szybsze i krótsze niż inne instrukcje mov wykonujące tą
samą pracę. Na przykład, obie instrukcje mov ax, mem i mov reg, mem mogą załadować rejestr ax z komórki
pamięci. We wszystkich procesorach, pierwsza wersja jest krótsza .We wcześniejszych członkach rodziny
80x86 jest również szybsza.
Są dwa bardzo ważne szczegóły dotyczące instrukcji mov. Po pierwsze nie ma operacji przeniesienia z
pamięci do pamięci. tryb adresowania bajt mod-reg-r/m. (zobacz Rozdział Czwarty) pozwala na to dwóm
operandom rejestrowym lub jednemu operandowi rejestrowemu i jednemu operandowi pamięci.. nie ma formy
instrukcji mov, która pozwala nam kodować dwa adresy pamięci w tej samej instrukcji. Po drugie, nie możemy
bezpośrednio przenieść danych do rejestru segmentowego. Instrukcje które przenoszą dane do lub z rejestru
segmentowego mają bajty mod-reg-r/m. ;nie ma formy która przenosi bezpośrednie wartości do rejestru
segmentowego .Dwa powszechne błędy robione przez początkujących programistów to próby przenoszenia z
pamięci do pamięci i próby ładowania stałej do rejestru segmentowego.
Operandami instrukcji mov mogą być bajty, słowa lub podwójne słowa. Oba operandy muszą być tego
samego rozmiaru lub MASM wygeneruje błąd podczas asemblowania naszego programu. To ma zastosowanie
do operandu pamięci i rejestru. Jeśli deklarujemy zmienną B, używając byte i próbujemy załadować tą zmienną
do rejestru ax ,MASM zgłosi konflikt typów.
CPU rozszerza dane bezpośrednie do rozmiaru operandu przeznaczenia (chyba ,że jest zbyt duży do
umieszczenia w operandzie przeznaczenia, wtedy mamy błąd).Zauważmy, że możemy przenieść wartości
bezpośrednie do komórki pamięci. Ta sama zasada dotyczy stosowanego rozmiaru. Jednak MASM nie może
ustalić rozmiaru pewnych operandów pamięci. Na przykład, czy instrukcja mov [bx],0 przechowuje wartość
ośmio- szesnasto- czy trzydziesto dwu bitową? MASM nie może powiedzieć wiec zgłasza błąd. Ten problem
nie istnieje, jeśli przenosimy dane do zmiennych, zadeklarowanych w naszym programie. Na przykład, jeśli
zadeklarujemy B jako zmienną bajtową, MASM wie, że ma przechować osiem bitów zero w B dla instrukcji
mov B,0.Tylko te operandy pamięci wymagające wskaźników bez zmiennych operandów
cierpią na ten
problem. Rozwiązaniem jest wyraźne powiedzenie MASMowi czy operand jest bajtem, słowem czy podwójnym
słowem, Możemy tego dokonać w następujących formach instrukcji:
mov byte ptr [bx],0
mov word ptr [bx],0
mov dword ptr [bx],0 (3)
(3) dostępne tylko na procesorach 80386 i późniejszych
Po więcej szczegółów na temat operatora type ptr zajrzyj do Rozdziału Ósmego.
Przeniesienia do i z rejestru segmentowego są zawsze 16 bitowe; operand mod-reg-r/m. musi być 16
bitowy albo MASM wygeneruje błąd. Ponieważ nie możemy załadować stałej bezpośrednio do rejestru
segmentowego ,popularnym rozwiązaniem jest ładowanie stałej do rejestru ogólnego przeznaczenia a potem
skopiowanie go do rejestru segmentowego. Na przykład, następujące dwie instrukcje ładują rejestr es wartością
40h:
mov ax,40h
mov es, ax
Zauważmy ,że prawie każdy rejestr ogólnego przeznaczenia jest wystarczający. Tutaj, ax został wybrany
przypadkowo.
Instrukcja mov nie wymaga żadnych flag. W szczególności,80x86 zachowuje wartości flag po
wykonaniu instrukcji mov.
6.3.2 INSTRUKCJA XCHG
Instrukcja xchg (exchange) zamienia miejscami dwie wartości. Ogólna jej forma to
xchg operand
1
, operand
2
Są cztery specyficzne formy tej instrukcji w 80x86:
xchg reg, mem
xchg reg, reg
xchg ax, reg
16
xchg eax, reg
32
(3)
(3) dostępne tylko na procesorze 80386 i późniejszych
Pierwsze dwie formy ogólne wymagają dwóch lub więcej bajtów na opcody i bajty mod-reg-
r/m.(przemieszczenie, jeśli jest konieczne ,wymaga dodatkowego bajtu).Trzecia i czwarta forma są specjalnymi
formami drugiej, która zamienia dane w rejestrze (e)ax z innym 16- lub 32 bitowym rejestrem. Forma 16 bitowa
używa pojedynczego bajtu opcodu, który jest krótszy niż pozostałe dwie formy, które używają jednego bajtu
opcodu i bajtu mod-reg-r/m.
Powinniśmy zanotować wzorzec konstruowania: rodzina 80x86 często dostarcza krótszych i szybszych
wersji instrukcji ,które używają rejestry ax. Dlatego też, powinniśmy próbować tak układać swoje obliczenia
aby używać rejestru (e)ax tak często jak to możliwe. Instrukcja xchg jest doskonałym przykładem, forma, która
zamienia 16 bitowe rejestry jest długa na jeden bajt.
Zauważmy, że porządek operandów xchg nie ma znaczenia. To znaczy możemy wprowadzić xchg
mem, reg i otrzymać ten sam wynik jak przy xchg reg, mem. Większość nowoczesnych asemblerów
automatycznie emituje opcod dla krótszej instrukcji xchg ax, reg jeśli wyszczególnimy xchg reg, ax.
Oba operandy muszą być tego samego rozmiaru .Na procesorach przed 80386, operandy mogą być
ośmio- lub szesnasto bitowe. Na procesorach 80386 i późniejszych operandy mogą być długie na 32 bity.
Instrukcja xchg nie modyfikuje żadnych flag.
6.3.3 INSTRUKCJE LDS,LES,LFS,LGS I LSS
Instrukcje lds ,les, lfs, lgs i lss pozwalają nam załadować 16 bitowy rejestr ogólnego przeznaczenia i
rejestr segmentowy pojedyncza instrukcją W 80296 i wcześniejszych, instrukcje lds i les są instrukcjami, które
bezpośrednio przetwarzają wartości większe iż 32 bity. Ogólna forma:
LxS prez. , źródło
Te instrukcje przyjmują takie formy:
lds
reg
16
, mem
32
les
reg
16
, mem
32
lfs
reg
16
, mem
32
(3)
lgs
reg
16
, mem
32
(3)
lss
reg
16
, mem
32
(3)
(3) dostępne na procesorach 80386 lub późniejszych
Reg
16
jest rejestrem ogólnego przeznaczenia a mem
32
jest komórką pamięci podwójnego słowa (zadeklarowaną
instrukcją dword).
Te instrukcje ładują 32 bitowe spod adresu wyspecyfikowanego przez mem
32
do reg
16
i rejestrów ds.,
es, fs, gs lub ss. ładują one rejestr ogólnego przeznaczenia najmniej znaczącym słowem operandu pamięci a
rejestr segmentowy słowem najbardziej znaczącym. Następujący algorytm opisuje dokładnie tą operację:
Ponieważ instrukcje LxS ładują rejestry segmentowe 80x86,nie wolno nam używać tych instrukcji dla
przypadkowych zadań. Użycie ich do ustawienia (dalekich) wskaźników do pewnych obiektów danych jest
omówione w Rozdziale Czwartym. Inne ich zastosowanie może spowodować problemy z naszym kodem jeśli
spróbujemy przenieść go na Windows,OS/2 lub UNIX.
Zapamiętajmy, że te instrukcje ładują cztery bajty spod danej komórki pamięci do pary rejestrów; one
nie ładują adresów zmiennych do pary rejestrów (tj. ta instrukcja nie ma trybu bezpośredniego).Jeśli chcemy się
nauczyć jak ładować adresy zmiennych do pary rejestrów ,zobaczymy to w Rozdziale Ósmym.
Instrukcje LxS nie wpływają na żaden bit flagi 80x86.
[ 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
- Różnice w sprawowaniu św. Liturgii w prawosławnych Kościołach lokalnych, Prawosławie
- zanotowane.pl
- doc.pisz.pl
- pdf.pisz.pl
- streamer.htw.pl