50 4. Język asemblerowy mikroprocesorów 8086/8088
; w kolejnym przykładzie zmienne zostają redefiniowane DANE SEGMENT
TABLICA DB 3 DUP (?) ; definiowanie trzech bajtów (zob. p. 4.3.2)
ORG OFFSET TABLICA ; operator OFFSET (zob. p. 4.4) ALA DB ’A’
KOT DW ’LA’ «
Dyrektywa EVEN | ||
Dyrektywa EVEN ustawia wskaźnik pozycji asemblera na adres, o ile aktualny jest nieparzysty (p. 2.5). |
najbliższy parzysty | |
Przykład DANE |
SEGMENT DB ? ; offset = 0 EVEN DD ? ; offset = 2 DB? |
♦ |
Dyrektywa ASSUME |
Dyrektywa ASSUME służy do deklarowania zawartości czterech rejestrów segmentowych w czasie realizacji programu. Asembler wykorzystuje tę informację celem określenia, czy zmienne i etykiety używane w segmencie są adresowane przez właściwy rejestr segmentowy. Także - w przypadku gdy jest to niezbędne - generuje odpowiednie przedrostki przyporządkowujące zmiennym inne niż standardowe rejestry segmentowe. Każda komórka pamięci jest określona przez 20-bitowy adres fizyczny oraz adres logiczny składający się z dwóch liczb 16-bitowych. Większość rozkazów komunikujących się z pamięcią używa jedynie 16-bitowego adresu względem początku segmentu, uwzględniając przy tym adres początku segmentu określony odpowiednim rejestrem segmentowym. Zatem aby obliczony w BIU adres fizyczny był prawidłowy, zawartość rejestrów segmentowych w czasie wykonywania programu musi być zgodna z deklaracją zawartości tych rejestrów w czasie asemblacji, co jest realizowane właśnie dyrektywą ASSUME. Dyrektywa ta musi więc znajdować się w programie źródłowym przed pierwszym użyciem rejestru segmentowego lub też przed każdą zmianą jego zawartości. Każde działanie na danych w programie lub na stosie wymaga wcześniejszego określenia zawartości rejestrów DS, SS, ES. Zatem dla tych rejestrów dyrektywa ASSUME musi znaleźć się w programie źródłowym przed rozkazami związanymi z dostępem do pamięci. Podobnie musi być zdefiniowany rejestr CS przed pierwszą instrukcją, która jest poprzedzona etykietą (adresem symbolicznym). Dzięki temu są też generowane właściwe kody rozkazów dla skoków bliskich (NEAR), tzn. wewnątrz segmentu lub grupy segmentów (zob. dyrektywa GROUP). W przypadku skoku dalekiego (FAR) tzn. między segmentami zostaje zmieniona zawartość rejestru segmentowego CS i w związku z tym rozkaz taki musi być poprzedzony nową deklaracją ASSUME. Składnia dyrektywy jest następująca
4.3. Dyrektywy i pseudoinstrukcje
powere^ by
Mi si ol
ASSUME reg seg: nazwa [,reg_seg: nazwa,...]
przy czym:
- dyrektywa nie może być poprzedzona nazwą,
- reg seg może być jednym z rejestrów CS, DS, SS, ES,
. nazwa jest nazwą określonego segmentu, grupy segmentów zdefiniowanej dyrektywą GROUP lub wyrażenie: SEG zmienna lub SEG etykieta (zob. komentarz do GROUP).
W przypadku, gdy w segmencie jeden z rejestrów segmentowych nie będzie używany, dyrektywa powinna mieć postać
ASSUME reg_seg: NOTHING
Umieszczenie w programie źródłowym dyrektywy ASSUME pozwala przy działaniu na zmiennych nie używać przedrostka, określającego przyporządkowany rejestr segmentowy.
Przykłady
DANE 1 SEGMENT GLOBAL
ZMIENNA 1 DB ? ZMIENNA 2 DB ? DANEl ENDS DANE2 SEGMENT
ZMIENNA 3 DW ? ZMIENNA 4 DW ? DANE2 ENDS PROGRAM SEGMENT PARA
ASSUME CS:PROGRAM ; nie ma deklaracji ASSUME dla danych
MOV AX, DANE l ; załadowanie rejestrów
MOV DS, AX ; segmentowych: DS
MOV AX, DANE 2 ; oraz
MOV ES, AX ; ES
; przedrostki są niezbędne MOV BX, ES:ZMIENNA_4 MOV CL, DS:ZMIENNA_1 MOV DH, DS:ZMIENNA_2
• ••
PROGRAM ENDS
Zastosowanie dyrektywy ASSUME do rejestrów DS i ES pozwoli w tym przypadku zniienić segment PROGRAM następująco PROGRAM SEGMENT PARA
ASSUME CS;PROGRAM, DS:DANE_1, ES:DANE_2 ; jest dyrektywa ASSUME dla danych MOV AX, DANE l ; załadowanie rejestrów
MOV DS, AX ; segmentowych: DS