Maciej Kostyra |
18-12-2000 |
Grupa III |
|
Temat:
|
Assembler |
Typy i zmienne strukturalne, cd.
Deklaracja zmiennych typu strukturowego ma postać:
lab name arg, arg, ... ,arg
w której lab jest etykietą, name jest nazwą typu strukturowego, a każde arg jest wyrażeniem inicjującym składającym się z listy inicjatorów ujętych w nawiasy kątowe. Każde z tych wyrażeń służy do zainicjowania jednego (ale tylko nazwanego) pola struktury. Jeśli pewien inicjator nie występuje, to zamiast niego domyślnie przyjmuje się inicjator wzięty z deklaracji typu. Zabrania się, aby rozmiar danej reprezentowany przez jawnie podany inicjator przekraczał rozmiar pola wynikający z deklaracji typu, a ponadto zabrania się użycia inicjatora mającego postać literału tekstowego, jeśli deklaracja pola nie zawierała takiego literału.
Przykład:
Deklarowanie struktur
W zasięgu deklaracji typu strukturowego Person
Person STRUC
Fullname DB `John Walker'
Age DW 40
Sex DB ?
Person ENDS
Napis:
Bob Person <'Bob Smith',,1>
jest deklaracją zmiennej strukturowej bob, składającej się z pól Fullname, Age i Sex o rozmiarach wziętych z deklaracji. Rozmiarami tymi są odpowiednio: 11 (mimo, że Bob Smith ma rozmiar 9), 2 i 1. Pole Age ma wartość określoną domyślnie (40), a dwa najmniej znaczące bajty pola Fullname są spacjami.
Wymaga się, aby w danym module źródłowym nazwy pól struktur i unii były niepowtarzalne. W celu umożliwienia odwoływania się do takich pól wprowadzono operator . (kropka), który w istocie może być traktowany dokładnie tak samo jak operator + (plus).
Przykład:
Przetwarzanie pól struktur
W zasięgu deklaracji typu strukturowego Date
Date STRUC
Year DW ?
Month DB ?,-1
Day DW ?
Date ENDS
…
TheDay Date <1981,12,13>
…
Wykonanie rozkazów:
mov bx, offset TheDay
mov ax, [bx.Year] ; ax=1981
mov ah, [TheDay.Month] ; ah=12
mov al, [byte ptr TheDay.Day] ; al=13
mov al, [TheDay.(Month+1)] ; al=-1
powoduje załadowanie rejestrów w sposób podany w komentarzach.
Dyrektywy deklarowania etykiet
Z każdą etykietą występującą w dyrektywie deklarowania zmiennych jest
związany jej typ :
Dyrektywa Typ
DB BYTE
DW WORD
DD DWORD
DF FWORD
DQ QWORD
DT TWORD
Etykieta odzielona od rozkazu znakiem : (dwukropek) jest typu NEAR, a etykieta poprzedzająca dyrektywę strukturalną PROC (stanowiącą deklarację procedury) jest typu określonego jawnie w tej dyrektywie (NEAR lub FAR), albo przyjętej domyślnie, zgodnie z modelem pamięci :
NEAR- dla modeli TINY, SMALL, COMPACT
FAR- dla modeli MEDIUM, LARGE, HUGE, TPASCAL
Ponadto typ etykiety może być deklarowany za pomocą dyrektywy LABEL .
Dyrektywa LABEL ma postać :
name LABEL type
w której name jest identyfikatorem deklarowanej etykiety, a type jest jej typem. Typ etykiety określa, czy dotyczy ona danych (np. BYTE, WORD, DWORD), czy rozkazów (np. NEAR, FAR). Zinterpretowanie dyrektywy LABEL powoduje opatrzenie następnego bajtu właśnie kompilowanego segmentu etykietą name. Tak zdefiniowana etykieta może być wyeksportowana do innego modułu
Przykład deklaracji etykiety
W zasięgu deklaracji
Lower LABEL BYTE
Fix DW 13
...
Before LABEL FAR
Start: mov ax, @data
After LABEL NEAR
Etykietami tutaj są nie tylko FIX i START, ale także LOWER, BEFORE i AFTER.W szczególności Lower jest nazwą zmiennej składającej się z mniej znaczącego bajtu zmiennej FIX, a Before jest etykietą rozkazu mov. W odróżnieniu od etykiety Start, która jest typu NEAR, etykieta Before jest typu FAR.
Wyrażenia
Wyrażenia mogą występować zarówno w argumentach dyrektyw deklarowania zmiennych, jak i w argumentach rozkazów. Wymaga się, aby każde wyrażenie było wyrażeniem stałym, tj. aby jego wartość dała się określić przed podjęciem wykonywania programu. Dzięki takiemu ustaleniu w każdym miejscu programu, w którym może wystąpić liczba może również wystąpić wyrażenie.
Składnia języka TurboAssembler jest bliższa składni języka TurboC, niż składni języka TurboPascal. Przejawia się to między innymi w tym, że wnioskowanie o poprawności i semantyce wyrażenia może być przeprowadzone wyłącznie na podstawie priorytetu użytych w nim parametrów.
Uporządkowanie operatorów w kolejności malejących priorytetów jest następująca:
< >, ( ), [ ], LAGTH, MASK, SIZE, WITH
.
+ - ( jednoargumentowe)
:
OFFSET type PTR SEG THIS TYPE
* / MOD SHL SHR
+ - (dwuargumentowe)
EQ GE GT LE LT NE
NOT
AND
OR XOR
SHORT
przy czym type oznacza jedno z następujących słów kluczowych:
FAR, NEAR, BYTE, WORD, DWORD, FWORD, QWORD, TBYTE
< >
Uznanie napisu <text> za literał, tj. nie wnikanie w znaczenie znaków stanowiących text.
Przykład:
W zapisie:
count <;a+b>
znak ; (średnik) nie rozpoczyna komentarza.
( )
Nadanie pierwszeństwa wyrażeniu w nawiasach.
Przykład:
W wyrażeniu:
a-(b+c)
najpierw jest wykonywane dodawanie
[ ]
Uznanie napisu [exp1] [exp2] za [exp1+exp2]
Przykład:
Uznanie rozkazu:
mov ax, [bx][2]
za równoważny rozkazowi:
mov ax, [bx+2]
LENGTH
Uznanie napisu LENGTH name, w którym name jest identyfikatorem zmiennej, za nazwę licznika zmiennych zadeklarowanych za pomocą słowa kluczowego DUP, albo za nazwę stałej 1, jeśli w deklaracji nie posłużono się tym słowem kluczowym.
Przykład:
W zasięgu deklaracji:
Count DW 10 DUP(20 DUP (?)),1000 DUP (0)
napis:
length Count
reprezentuje daną o wartości 10.
MASK
Uznanie napisu MASK field, w którym field jest nazwą pola rekordu, za nazwę maski umożliwiającej dokonanie wyboru pola.
Przykład:
W zasięgu deklaracji:
Rec RECORD West:2 , East:5
napis
mask West
reprezentuje daną o wartości 01100000B
SIZE
Uznanie napisu SIZE name za równy iloczynowi:
(LENGTH name) * (TYPE name)
Przykład:
W zasięgu deklaracji:
Array DW 10 DUP(0), 30 DUP(1)
napis:
Size Array
reprezentuje daną o wartości 20.
WIDTH
Uznanie napisu WIDTH field, w którym field jest nazwą rekordu albo identyfikatorem pola rekordu, za icznik bitów tego rekordu albo pola.
Przykład:
W zasięgu deklaracji:
Rec RECORD West:2, East:5
napisy:
Width Rec
i
Width East
reprezentują dane o wartościach odpowiednio 7 i 5.
.
Uznanie napisu .field, w którym field jest identyfikatorem pola struktury, za napis +field
Przykład:
W zasięgu deklaracji:
Child STRUC
Name DB '
Age DB ?
Child ENDS
...
Isa Child <Isabel, 6>
rozkaz
mov ah, [Isa.Age]
jest uznawany za rozkaz:
mov ah, [Isa+Age]
HIGH
Uznanie napisu HIGH exp, w którym exp jest wyrażeniem, za nazwę stałej bajtowej stanowiącej bardziej znaczącą część stałej reprezentowanej przez exp.
Przykład:
Napis:
high 1111000000001111B
Reprezentuje daną o wartości 11110000B
LOW
Uznanie napisu LOW exp, w którym exp jest wyrażeniem, za nazwę stałej bajtowej stanowiącej mniej znaczącą część stałej reprezentowanej przez exp.
Przykład:
Napis:
low 1111000000001111B
Reprezentuje daną o wartości 00001111B
+
Uznanie napisu +exp, w którym exp jest wyrażeniem, za wyrażenie exp.
Przykład:
Napis: 2 - + 3
reprezentuje daną o wartości -1
-
Uznanie napisu -exp, w którym exp jest wyrażeniem, za wyrażenie 0 - exp.
Przykład:
Napis: 2+(-3)
reprezentuje daną o wartości -1
:
Uznanie napisu seg:ofs, w którym seg jest nazwą rejestru segmentowego, nazwą segmentu albo nazwą grupy segmentów, a ofs jest wyrażeniem stałym, za przemieszczenie wyznaczone względem podanego rejestru, segmentu albo grupy segmentów.
Przykład:
Jeśli SI=2 to w rozkazie:
mov al., [cs: si+4]
nastąpi odwołanie do szóstego bajtu segmentu określonego przez CS.
OFFSET
Uznanie napisu offset addr, w którym addr jest adresem pamięci, za przemieszczenie tego adresu względem początku segmentu, w którym znajduje się addr.
Przykład:
Napis: offset DGROUP:FIX
reprezentuje przemieszczenie adresu FIX względem grupy DGROUP.
type PTR
Uznanie napisu type ptr exp, w którym type jest oznaczeniem typu:
BYTE, WORD, DWORD, FWORD, QWORD, TBYTE (dla danych)
NEAR, FAR, PROC (dla rozkazów),
a exp jest wyrażeniem, za wyrażenie typu type lokalizujące to samo miejsce pamięci co exp.
Przykład:
Uznanie, że w rozkazie:
inc [byte ptr bx]
rejestr BX lokalizuje daną typu BYTE.
SEG
Uznanie napisu SEG addr, w którym addr jest adresem pamięci, za numer segmentu zawierającego ten adres.
Przykład:
W zasięgu deklaracji:
Data SEGMENT
DB ?
FIX DW 13
Data ENDS
zarówno Seg Data jak i Seg Fix jest numerem segmentu, w którym zadeklarowano zmienną FIX.
type PTR
Uznanie napisu This type, w którym type jest oznaczeniem typu:
BYTE, WORD, DWORD, FWORD, QWORD, TBYTE (dla danych)
NEAR, FAR, PROC (dla rozkazów),
za pełny adres (numer segmentu i przeniesienie) w bieżącym miejscu kompilowania bieżącego segmentu.
Przykład:
Dyrektywa: Here EQU THIS FAR
Jest traktowana tak, jak dyrektywa: Here LABEL FAR
1