ROZDZIAŁ ÓSMY MASM DYREKTYWY I PSEUDO-OPCODY, 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
konsultacja naukowa: NEKRO
wankenob@priv5.onet.pl
nekro@pf.pl
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
ROZDZIAŁ ÓSMY :
MASM: DYREKTYWY I PSEUDO-OPCODY
Instrukcje takie jak mov ax,0 i add ax, bx są niezrozumiałe dla mikroprocesora. W takiej postaci w
jakiej te instrukcje się pojawiają, są one jeszcze czytelnymi dla ludzi postaciami instrukcji 80x86.80x86 reaguje
na polecenia takie jak B80000 i 03C3.Assembler jest programem który konwertuje łańcuchy takie jak mov ax, 0
do kodu maszynowego 80x86 „B80000”.Każdy program w języku asemblera zawiera instrukcje takie jak mov
ax, 0.Assembler konwertuje każdy asemblerowy plik źródłowy do kodu maszynowego – binarny odpowiednik
programu asemblerowego. Pod tym względem program asemblerowy jest jak kompilator, odczytuje plik
źródłowy ASCII z dysku i tworzy na wyjściu program języka maszynowego. Główna różnica między
kompilatorem dla języka wysokiego poziomu (HLL) takim jak Pascal i asemblerem jest taka, że kompilator
zwykle emituje kilka instrukcji maszynowych dla każdej instrukcji pascalowskiej .Asembler generalnie emituje
pojedynczą instrukcję maszynową dla każdej instrukcji języka asemblera.
Próba napisania programu w języku maszynowym (tj. w binarnym) nie jest szczególnie miła. Proces ten
jest bardzo nużący, skłonny do błędów i nie proponujący żadnych korzyści przy programowaniu w języku
asemblera .Jedyną główną wadą języka asemblera przy czystym kodzie maszynowym jest to ,że musimy
najpierw assemblować i linkować program przed jego wykonaniem. Jednakże, próba asemblowania kodu ręcznie
będzie trwała dłużej niż mała ilość czasu jaką poświęci asembler na wykonanie tego za nas.
Jest inna wada nauki języka asemblera .Asembler taki jak Microsoft’s Macro Assembler (MASM)
dostarcza dużej liczby możliwości dla programisty asemblerowego. Chociaż nauka o tych możliwościach zabiera
sporo czasu, są one bardzo użyteczne i warte włożonego wysiłku.
8.0 WSTĘP
Podobnie jak w Rozdziale Szóstym, dużo informacji w tym rozdziale jest materiałami odnośnymi.
Podobnie jak każda sekcja odnośna, jakaś wiedza jest niezbędna, inny materiał jest przydatny ale opcjonalny, a
niektórych materiałów możemy nigdy nie używać podczas pisania programów. Poniższa lista przedstawia
informacje w tym tekście. Symbol „•” oznacza materia niezbędny, symbol „⊗” oznacza opcjonalny i mniej
użyteczny temat.
• Format źródłowy instrukcji języka asemblera
⊗ Licznik lokacji
• Symbole i identyfikatory
• Stałe
• Deklaracje procedur
⊗ Segmenty w programie języka asemblera
• Zmienne
• Typy symboli
• Wyrażenia adresowe (późniejsze podsekcje zawierają materiał zaawansowany)
⊗ Warunkowe asemblowanie
⊗ Makra
⊗ Dyrektywy listowania
⊗ Oddzielne asemblowanie
8.1 INSTRUKCJE JĘZYKA ASSEMBLERA
Instrukcje w języku assemblera w pliku źródłowym używają następującego formatu:
{Etykieta} {Mnemonik {Operand}} {;Komentarz}
Każda powyższa jednostka jest polem Cztery powyższe pola są to pole etyliety, pole mnemonika, pole
operandu i pole komentarza.
Pole etykiety jest (zazwyczaj) polem opcjonalnym zawierającym etykietę symboliczną dla bieżącej
instrukcji. etykiety są używane w języku assemblera, podobnie jak w HLL, do oznaczania linii jako celu skoków
GOTO .Możemy również wyszczególnić nazwę zmiennej, nazwę procedury i inne jednostki używające etykiet
symbolicznych. Przez większość czasu pole etykiety jest opcjonalne, w znaczeniu, że etykieta może być obecna
tylko, jeśli chcemy etykietę na tej szczególnej linii. Niektóre mnemoniki, jednak wymagają etykiety, inne nie.
Generalnie ,powinniśmy zawsze zaczynać nasze etykiety w pierwszej kolumnie (uczyni to nasz program
łatwiejszym w czytaniu).
Mnemonik jest nazwą instrukcji (np. mov, add itp.)Słowo mnemonik oznacza wspomaganie pamięci.
mov jest dużo łatwiejsze do zapamiętania niż binarny odpowiednik instrukcji mov! Nawiasy klamrowe
oznaczają, że ta pozycja jest opcjonalna. Zauważmy jednak, że nie możemy mieć operandu bez mnemonika.
Pole mnemonika zawiera instrukcję assemblera .Instrukcje są dzielone na trzy klasy :instrukcje
maszynowe 80x86,dyrektywy assemblera i pseudo opcody .Instrukcje 80x86 są oczywiście mnemonikami
assemblera ,które odpowiadają rzeczywistym instrukcjom 80x86 wprowadzonym w Rozdziale Szóstym.
Dyrektywy assemblera są instrukcjami specjalnymi które dostarczają informacji do assemblera ale nie
generują żadnego kodu. Przykłady obejmują dyrektywę segment, equ, assume i end. Te mnemoniki nie są
ważnymi instrukcjami 80x86.Są one tylko informacjami dla assemblera ,niczym więcej.
Pseudo-opcody są wiadomością dla assemblera, podobnie jak dyrektywy, jednak pseudo-opcod
wyemituje bajt kodu wynikowego.. Przykłady pseudo-opcodów obejmują byte ,word, dword, qword i tbyte.
Instrukcje te emitują bajty danych wyszczególnione przez ich operandy ale nie są prawdziwymi instrukcjami
maszynowymi 80x86.
Pole operandu zawiera operandy lub parametry ,dla instrukcji wyszczególnionej w polu mnemonika.
Operandy nigdy nie pojawiają się w wierszu same z siebie. Typ i liczba operandów (zero, jeden, dwa lub więcej)
zależy wyłącznie od określonej instrukcji.
Pole komentarza pozwala nam opisać każdą linie kodu źródłowego w naszym programie. .Zauważmy
,że pole komentarza zawsze zaczyna się od średnika. Kiedy asembler przetwarza linię tekstu, kompletnie
ignoruje wszystko w linii źródłowej występujące za średnikiem.
Każda instrukcja języka assemblera pojawia się we własnym wierszu w pliku źródłowym. nie możemy
mieć wielu instrukcji w pojedynczej linii. Z drugiej strony, ponieważ wszystkie pola w instrukcji języka
assemblera są opcjonalne, linie puste są w porządku. Możemy użyć pustych linii gdziekolwiek w naszym pliku
źródłowym. Linie puste są użyteczne przy rozmieszczaniu pewnych sekcji kodu, czyniąc je łatwiejszymi do
czytania.
Microsoft Macro Assembler jest asemblerem o swobodnej formie. Różne pola instrukcji języka
assemblera mogą pojawiać się w każdej kolumnie (chociaż lepiej ,żeby pojawiały się we właściwym porządku)
Każda liczba spacji lub tabulatorów może oddzielać różne pola w instrukcji. Dla assemblera, te dwie sekwencje
kodu są identyczne
----------------------------------------------------------
mov ax, 0
mov bx, ax
add ax ,dx
mov cx, ax
-----------------------------------------------------------
mov
ax,
0
mov bx,
ax
add ax, dx
mov cx,ax
-------------------------------------------------------------
Pierwsza sekwencja kodu jest dużo łatwiejsza do odczytu niż druga (jeśli tak nie sądzisz, być może
powinieneś zobaczyć się z lekarzem!)
Umieszczenie etykiety w kolumnie jeden, mnemoników w kolumnie 17 (dwa tabulatory),pola
operandu w kolumnie 25 (trzy tabulatory) i komentarza około kolumny 41 lub 49 (pięć lub sześć tabulatorów)
tworzy najlepiej wyglądający listing. Programy w języku assemblera, takie jak ten , są dosyć trudne do
odczytania. formatowanie naszego listingu pomoże uczynić go łatwiejszym do odczytu i uczyni łatwiejszym do
pielęgnacji.
Możemy mieć sam komentarz w linii. W takim przypadku, umieszczamy średnik w kolumnie jeden i
używać całej linii dla komentarza ,przykłady:
;Następująca sekcja kodu pozycjonuje kursor w górnej, lewej części ekranu:
mov
X, 0
mov
Y, 0
8.2 LICZNIK LOKACJI
Przypomnijmy, że wszystkie adresy w przestrzeni pamięci 80x86 składa się z adresu segmentowego i
offsetu wewnątrz segmentu. Assembler, w trakcie konwertowania naszego pliku źródłowego do kodu
wynikowego, musi zachować ścieżkę offsetu wewnątrz bieżącego segmentu. Licznik lokacji jest zmienną
assemblera która to obsługuje.
Kiedy tworzymy segment w naszym pliku źródłowego języka assemblera, assembler kojarzy z nim
wartość bieżącego licznika lokacji. Licznik lokacji zawiera bieżący offset do tego segmentu. Pierwotnie (kiedy
assembler po raz pierwszy napotyka segment) licznik lokacji jest ustawiony na zero. Kiedy napotyka instrukcję
lub pseudo-opcodu, MASM zwiększa licznik lokacji dla każdego bajtu zapisanego w pliku kodu wynikowego.
Na przykład, MASM zwiększa licznik lokacji o dwa po napotkaniu mov ax, bx ponieważ instrukcja ta jest
dwubajtowa.
Wartość licznika lokacji zmienia się w całym procesie asemblacji. Zmienia się dla każdej linii kodu w
naszym programie, kiedy tworzymy kod wynikowy .Będziemy używać terminu licznik lokacji w znaczeniu
wartości licznika lokacji przy poszczególnej instrukcji przed wygenerowaniem jakiegoś kodu. Rozważmy
następujące instrukcje języka assemblera:
0:
or
ah, 9
3:
and
ah,0c9h
6:
xor
ah,40
9:
pop
cx
A:
mov
al.,cl
C:
pop
bp
D:
pop
cx
E:
pop
dx
F:
pop
ds.
10: ret
Instrukcje or, and i xor ,wszystkie są długości trzech bajtów, instrukcja mov jest dwubajtowa; pozostałe
instrukcje wszystkie są jednobajtowe. Jeśli te instrukcje pojawią się na początku segmentu, licznik lokacji będzie
taki sam jak liczby które pojawiają się bezpośrednio na lewo od każdej powyższej instrukcji. Na przykład,
instrukcja or zaczyna się od offsetu zero, ponieważ instrukcja or jest trzybajtowa ,następna instrukcja (and)
wystąpi pod offsetem trzy. Podobnie and jest trzybajtowa ,więc xor wystąpi od offsetu sześć itd.
8.3 SYMBOLE
Rozważmy na chwilę instrukcję jmp. Instrukcja ta przyjmuje formę:
jmp cel
Cel jest adresem przeznaczenia. Wyobraźmy sobie jak żmudne byłoby gdybyśmy musieli w rzeczywistości
wyszczególnić adres docelowy pamięci jako wartość liczbową. Jeśli kiedyś programowaliśmy w BAISICu,
doświadczylibyśmy około 10% problemów jakie mielibyśmy w języku assemblera gdybyśmy musieli
wyszczególniać cel dla jmp poprzez adres.
Dla ilustracji, przypuśćmy, że chcielibyśmy skoczyć do pewnej grupy instrukcji którą jeszcze piszemy..
Jaki jest adres instrukcji docelowej? Jak możemy powiedzieć że napisaliśmy jakąś instrukcję przed instrukcją
docelową? Co się zdarzy jeśli zmienimy program (pamiętajmy, wprowadzenie i kasowanie instrukcji powoduje,
że wartość licznika lokacji dla wszystkich następnych instrukcji wewnątrz tego segmentu zmienia się).Na
szczęście ,wszystkie te problemy są zmartwieniem programistów języka maszynowego. Programiści języka
assemblera mogą zająć się adresami w dużo bardziej rozsądny sposób – poprzez użycie adresów
symbolicznych.
Symbol, identyfikator lub etykieta, jest nazwą powiązana z jakąś szczególną wartością. Wartość ta
może być offsetem wewnątrz segmentu, stałą, łańcuchem, adresem segmentowym, offsetem wewnątrz rekordu
lub nawet operandem dla instrukcji. W każdym razie, etykieta zapewnia nam możliwości do przedstawiania
niezrozumiałych wartości ,jako dobrze znanej mnemonicznej nazwy.
Nazwa symboliczna składa się z sekwencji liter, cyfr i znaków specjalnych, z następującymi
ograniczeniami:

Symbol nie może zaczynać się od cyfry

Nazwa może mieć każdą kombinację dużych i małych liter. Assembler traktuje duże i małe litery
równorzędnie.

Symbol może zawierać każdą liczbę znaków, jednak tylko pierwsze 31 jest używanych. Assembler
ignoruje wszystkie znaki po trzydziestym pierwszym

Symbole „_,$,? I @” mogą się pojawiać gdziekolwiek wewnątrz symbolu. jednak ,$ i ? są
symbolami specjalnymi; nie możemy tworzyć symbolu składającego się wyłącznie z tych dwóch
symboli.

Symbol nie może pokrywać się z żadną z nazw ,które są zarezerwowanymi symbolami.
Następujące symbole są zarezerwowane:
W dodatku, wszystkie poprawne nazwy instrukcji 80x86 i nazwy rejestrów są również zarezerwowane.
Zauważmy ,że lista ta stosuje się dla MASMa w wersji 6.0.Wcześnejsze wersje tego assemblera mają mniej
zarezerwowanych słów. Późniejsze wersje mogą mieć więcej
Kilka przykładów poprawnych symboli:
L1
Bletch
RightHere
Right_Here
Item1
_Special
$1234
@Home
$_@1
Dollar$
WhereAmI
@1234
$1234 i @1234 są zupełnie poprawne, chociaż mogą wydawać się dziwne.
Kilka przykładów niewłaściwych symboli:
1TooMany
- zaczyna się cyfrą
Hello.There -zawiera kropkę w środku symbolu
$ -nie może być samodzielnego znaku $ i >
LABEL -zarezerwowane słowo assemblera
Right Here -Symbol nie może zawierać spacji
Hi,There - lub innego znaku specjalnego poza _,?,$ i @
Symbolom, jak wspomniano wcześniej, można przydzielić wartości liczbowe (takie jak wartości
licznika lokacji),łańcuchy lub nawet całe operandy. Wyjaśnijmy sobie jedną rzeczy, assembler przydziela typ do
każdego symbolu. Przykłady typów near, far, byte, word, double word, quad word, text i string. jak
zadeklarować etykiety pewnych typów jest tematem reszty tego rozdziału. Zauważmy, że assembler zawsze
przydziela jakiś typ do etykiety i będzie dozorował czy próbujemy użyć etykiety w miejscu gdzie nie jest
dozwolony taki typ etykiety.
8.4 STAŁE ZNAKOWE
MASM jest zdolny do przetwarzania pięciu różnych typów stałych: całkowite, całkowite upakowane
dziesiętne kodowane binarnie, liczby rzeczywiste, łańcuchy i tekst. W rozdziale tym zajmiemy się tylko stałymi
całkowitymi, rzeczywistymi, łańcuchami i tekstem. Po więcej informacji o wartościach całkowitych
upakowanych BCD, proszę zgłosić się do Przewodnika MASM.
Stała znakowa jest jedną której wartość jest ukryta pod znakami, które stanowią stałą. Przykłady stałych
znakowych:

123

3.14159

„Łańcuchowa Stała Znakowa”

0FABCh

‘A’

<Stała Tekstowa>
Oprócz ostatniego przykładu, większość stałych znakowych powinny być dobrze znane każdemu kto pisał
programy w językach takich jak Pascal lub C++. Stałe tekstowa są specjalnymi formami łańcuchów które
pozwalają na zastąpienie tekstowe podczas asemblacji.
Przedstawianie stałych znakowych odpowiada temu co normalnie moglibyśmy oczekiwać dla „wartości
rzeczywistego słowa” .Stałe znakowe są również znane jako „stałe nie symboliczne” ponieważ używają wartości
rzeczywistych ,zamiast jakichś nazw symbolicznych, wewnątrz naszego programu. MASM również pozwala
nam zdefiniować symboliczną lub jawną stałą w programie, ale więcej o tym później.
8.4.1 STAŁE CAŁKOWITE
Stała całkowita jest wartością liczbową, która może być określona jako binarna, dziesiętna lub
heksadecymalna. Wybór bazy (lub podstawy systemu liczbowego) należy do nas. Poniższa tablica pokazuje
poprawne cyfry dla każdej podstawy:
Tablica 35 Cyfry używane dla każdej podstawy systemu liczbowego
Dla odróżnienia pomiędzy liczbami w kilku systemach liczbowych, używamy znaku przyrostka. Jeśli,
kończymy liczbę „b” lub „B”, wtedy MASM zakłada, że jest to liczba binarna. Jeśli zawiera każdą inną cyfrę niż
zero lub jeden assembler wygeneruje błąd .Jeśli przyrostek to „t”, ”T” ,”d” lub „D”, wtedy assembler zakłada, że
jest to wartość dziesiętna (o podstawie 10).Przyrostek „h” lub „H” wybierze podstawę heksadecymalną.
Wszystkie stałe całkowite muszą zaczynać się cyfrą dziesiętną, wliczając w to stałe heksadecymalne.
Przedstawienie wartości „FDED” musi wyszczególnić 0FDEDh.Czołowa cyfra dziesiętna jest wymagana przez
assembler ,żeby mógł rozróżniać pomiędzy symbolami i stałymi numerycznymi; pamiętajmy ,”FDED” jest
zupełnie poprawnym symbolem MASMa.
Przykłady:
0F000h
12345d
0110010100b
[ Pobierz całość w formacie PDF ]

  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • tejsza.htw.pl
  •