Dyrektywy [ 484872 kB ]

Transkrypt

Dyrektywy [ 484872 kB ]
Dyrektywy asemblerowe
Asembler A51 ma kilka dyrektyw, które pozwalają na definiowanie symboli, wartości, rezerwację i
inicjalizację pamięci oraz sterowanie umiejscowieniem kodu programu. Dyrektywy nie powinny być mylone z
instrukcjami. Nie wytwarzają one wykonywalnego kodu i za wyjątkiem dyrektyw DB i DW nie wpływają
bezpośrednio na zawartość kodu programu.
Poniższa tabela pokazuje ogólny przegląd dyrektyw asemblerowych.
Dyrektywa
SEGMENT
RSEG
CSEG
BSEG
DSEG
ISEG
XSEG
EQU
SET
BIT
CODE
DATA
IDATA
XDATA
DB
DW
DBIT
DS
PUBLIC
EXTRN
NAME
ORG
USING
END
Format
Opis
Segmenty
segment SEGMENT klasa
Definicja segmentu relokowalnego
RSEG segment
Wybór segmentu relokowalnego
CSEG [AT adres_absolutny]
Definicja segmentu absolutnego w przestrzeni
pamięci kodu
BSEG [AT adres_absolutny]
Definicja segmentu absolutnego w przestrzeni
pamięci danych adresowanej bitowo
DSEG [AT adres_absolutny]
Definicja segmentu absolutnego w przestrzeni
wewnętrznej pamięci danych adresowanej
bezpośrednio
ISEG [AT adres_absolutny]
Definicja segmentu absolutnego w przestrzeni
wewnętrznej pamięci danych adresowanej pośrednio
XSEG [AT adres_absolutny]
Definicja segmentu absolutnego w zewnętrznej
przestrzeni pamięci danych
Definicje symboli
symbol EQU wyrażenie
Trwałe przypisanie wartości symbolowi
symbol SET wyrażenie
Czasowe przypisanie wartości symbolowi
symbol BIT adres_bitu
Definicja adresu bitu w bitowej przestrzeni danych
symbol CODE adres_kodu
Przypisanie symbolowi określonego adresu w
przestrzeni pamięci kodu
symbol DATA adres_danej
Przypisanie symbolowi określonego adresu z
wewnętrznej przestrzeni danych adresowanej
bezpośrednio
symbol IDATA adres_danej
Przypisanie symbolowi określonego adresu z
wewnętrznej przestrzeni danych adresowanej
pośrednio
symbol XDATA adres_danej
Przypisanie symbolowi określonego adresu z
zewnętrznej przestrzeni danych
Inicjalizacja pamięci kodu
[etykieta:] DB wyrażenie [,wyrażenie,...] Tworzy listę wartości, każda o rozmiarze bajta
[etykieta:] DW wyrażenie [,wyrażenie,...] Tworzy listę wartości, każda o rozmiarze słowa
Rezerwacja pamięci danych
[etykieta:] DBIT wyrażenie
Rezerwuje w pamięci określoną wyrażeniem liczbę
bitów
[etykieta:] DS wyrażenie
Rezerwuje w pamięci określoną wyrażeniem liczbę
bajtów
Łączenie programów
PUBLIC symbol [, symbol]
Określa symbole, które mogą być użyte poza
bieżącym modułem
EXTRN klasa [:typ] (symbol [, ...])
Definiuje odwołania do symboli w bieżącym module,
które zostały zdefiniowane w innym module
NAME nazwa_modułu
Określa nazwę bieżącego modułu
Przełączanie adresów
ORG wyrażenie
Określa umiejscowienie bieżącego segmentu
USING wyrażenie
Określa predefiniowany adres rejestru symbolicznego
i rezerwuje przestrzeń dla określonego banku
rejestrów
Inne
END
Wskazuje koniec programu
1
Dyrektywy związane z segmentami
Segment jest blokiem pamięci kodu lub danych, który tworzy asembler z kodu lub danych znajdujących
się w pliku źródłowym. Użycie segmentów w module źródłowym jest zależne od złożoności aplikacji. Małe
aplikacje wymagają mniejszej pamięci i są zwykle mniej złożone niż duże, wielomodułowe aplikacje.
Mikrokontroler MCS-51 ma kilka różnych, specyficznych dla siebie, przestrzeni pamięci. Segmenty są
więc używane do umiejscowienia kodu programu, stałych i zmiennych w tych przestrzeniach.
Licznik położenia
Podczas swojej pracy asembler A51 stosuje dla każdego segmentu tzw. licznik położenia, który jest
wskaźnikiem adresu w przestrzeni aktywnego segmentu. Adres ten jest adresem względnym dla segmentu
relokowalnego lub adresem bezwzględnym (rzeczywistym) dla segmentu absolutnego. Kiedy dany segment jest
po raz pierwszy aktywowany, licznik położenia jest ustawiany na 0. Wartość jego jest zmieniana po każdej
instrukcji o długość tej instrukcji, tj. o ilość bajtów jaką zajmie ta instrukcja w pamięci. Dyrektywy inicjalizacji i
rezerwacji pamięci (np. DS, DB lub DBIT) zmieniają wartość licznika położenia po przydzieleniu pamięci przez
tą dyrektywę. Dyrektywa ORG ustawia nową wartość dla licznika położenia. Jeśli nastąpi zmiana aktywnego
segment na inny, a potem powrót do niego, to licznik położenia przyjmuje taką wartość, jaką miał ostatnio przy
korzystaniu z danego segmentu. Zawsze, kiedy asembler napotka etykietę, to przypisuje jej bieżącą wartość
licznika położenia i typ bieżącego segmentu dla tej etykiety.
Znak dolara ($) sygnalizuje wartość licznika położenia w aktywnym segmencie. Kiedy używa się
symbolu $, należy pamiętać, że jego wartość zmienia się z każdą instrukcją, lecz tylko po tym, jak instrukcja ta
zostanie całkowicie zanalizowana przez asembler. Jeśli użyje się znaku $ w miejscu operandu instrukcji lub
dyrektywy, to reprezentuje on wtedy adres pierwszego bajta tej instrukcji.
Segmenty relokowalne
Segmenty relokowalne mają swoją nazwę, klasę jak również inne atrybuty. Segmenty relokowalne o tej
samej nazwie lecz umieszczone w różnych modułach obiektowych są uważane jako części tego samego
segmentu i są nazywane segmentami częściowymi. Są łączone podczas linkowania przez program linkera.
Segmenty relokowalne są tworzone przy użyciu dyrektywy SEGMENT, w której trzeba określić nazwę
segmentu i jego klasę.
Na przykład
MOJPROG
SEGMENT
CODE
definiuje segment o nazwie MOJPROG w klasie pamięci CODE. Oznacza to, ze wszystko, co pojawi się w tym
segmencie będzie umieszczone w pamięci programu.
Po definicji nazwy segmentu relokowalnego należy go wybrać wykorzystując dyrektywę RSEG. Kiedy
dyrektywa RSEG zostaje wykorzystana do wybrania segmentu, to staje się on aktywnym segmentem dla
asemblera, dopóki nie zostanie wybrany inny segment przez dyrektywę RSEG lub przez dyrektywę określającą
segment absolutny. Na przykład
RSEG
MOJPROG
wybiera segment MOJPROG zdefiniowany powyżej.
SEGMENT
Dyrektywa SEGMENT jest używana do deklaracji segmentów relokowalnych (adres absolutny
ustalany jest dopiero na poziomie linkowania). Dyrektywa ta ma następujący format:
segment
segment
SEGMENT
klasa
jest nazwą symboliczną przypisaną do segmentu. Nazwa ta jest następnie wykorzystywana w
dyrektywie RSEG. Nazw symboliczna segmentu może być również wykorzystywana w
wyrażeniach do reprezentowania adresu bazowego połączonych segmentów, który zostanie
obliczony przez linker.
2
klasa
jest klasą pamięci, w jakiej ma być ulokowany segment (patrz tabela poniżej).
Nazwa każdego segmentu w module musi być unikalna. W procesie linkowania łączone są segmenty
tego samego typu. Nazwa segmentu, jeśli jest związana z tą samą klasą segmentu, może powtarzać się w innych
modułach łączonych przez linker w jeden wspólny segment. Poniższa tabela przedstawia klasy pamięci.
Klasa
BIT
CODE
DATA
IDATA
XDATA
Opis
Wewnętrzna pamięć danych adresowana bitowo (20H .. 2FH).
Pamięć programu.
Wewnętrzna pamięć danych adresowana bezpośrednio (00H .. 7FH i rejestry SFR).
Wewnętrzna pamięć danych adresowana pośrednio (00H .. FFH).
Zewnętrzna pamięć danych.
Przykład:
MOJPROG
SEGMENT
DANE
SEGMENT
CODE
;definicja segmentu o nazwie MOJPROG
;w pamięci programu
XDATA ;definicja segmentu o nazwie DANE
;w zewnętrznej pamięci danych
RSEG
Dyrektywa RSEG rozpoczyna segment relokowalny, który został wcześniej zadeklarowany przy
wykorzystaniu dyrektywy SEGMENT. Dyrektywa RSEG ma następujący format:
RSEG
segment
segment
jest nazwą segmentu, która została wcześniej zdefiniowana przy użyciu dyrektywy
SEGMENT. Raz rozpoczęty segment pozostaje ważny, dopóki nie zostanie rozpoczęty nowy
segment.
Linker łączy segmenty w takiej kolejności, w jakiej występują polecenia SEGMENT.
Przykład:
MOJPROG
SEGMENT
RSEG
CODE
MOJPROG
MOV A,#0
MOV P0,A
...
...
Segmenty bezwzględne (absolutne)
Segmenty absolutne rezydują w określonym typie pamięci pod stałym adresem ustalanym przez
programistę na poziomie pisania kodu programu. Są one tworzone przy użyciu dyrektyw: CSEG, BSEG, DSEG,
ISEG i XSEG. Dyrektywy te umożliwiają umieszczanie kodu i danych lub rezerwację przestrzeni pamięci pod
określonym adresem. Segmenty absolutne są używane wtedy, gdy istnieje konieczność posiadania dostępu do
stałego miejsca w pamięci lub umieszczenia kodu lub stałych pod stałym adresem.
Po resecie mikrokontroler rozpoczyna wykonywanie programu od adresu 0. Aby wymusić
umieszczenie kodu programu od innego adresu należy wykorzystać segmenty absolutne. Poniższy przykład
przedstawia fragment programu, gdzie wymuszono w początkowej fazie jego wykonywania, skok do
podprogramu inicjalizującego, który jest umieszczony dalej w przestrzeni kodu.
...
CSEG AT 0
RESET_VECT: LJMP STARTUP
...
3
Kod programu, który został umieszczony od adresu 0000H za pomocą dyrektywy CSEG AT 0
wykonuje operację skoku pod etykietę STARTUP.
BSEG, CSEG, DSEG, ISEG, XSEG
Dyrektywy BSEG, CSEG, DSEG, ISEG, XSEG określają segmenty absolutne (adres takiego
segmentu jest ustalany przez programistę już w chwili pisania programu). Dyrektywy te mają następujący
format:
BSEG
CSEG
DSEG
ISEG
XSEG
adres
AT
AT
AT
AT
AT
adres
adres
adres
adres
adres
definiuje bezwzględny adres w segmencie BIT
definiuje bezwzględny adres w segmencie CODE
definiuje bezwzględny adres w segmencie DATA
definiuje bezwzględny adres w segmencie XDATA
definiuje bezwzględny adres w segmencie IDATA
jest bezwzględnym adresem bazowym, od którego będzie rozpoczynał się segment. Adres nie
może zawierać odniesień w przód i musi być wyrażeniem, które po obliczeniu daje konkretną
wartość.
BSEG, CSEG, DSEG, ISEG, XSEG określają segmenty absolutne odpowiednio w: przestrzeni danych
adresowanych bitowo, przestrzeni kodu, wewnętrznej przestrzeni danych adresowanych bezpośrednio,
wewnętrznej przestrzeni danych adresowanych pośrednio, zewnętrznej przestrzeni danych. Użycie tej dyrektywy
powoduje, że program asemblujący kończy wcześniejszy segment, jeśli taki był, w danym typie pamięci i tworzy
nowy w określonej klasie pamięci, rozpoczynając go od adresu podanego w instrukcji. Jeśli w instrukcji nie
zostanie określony adres, to jest kontynuowany ostatni bezwzględny segment danego typu. Jeśli wcześniej nie
został określony żaden segment bezwzględny tego typu, a w instrukcji nie określono adresu, to nowy segment
jest tworzony od adresu 0.
Przykłady:
DEC_FLAGA:
INC_FLAGA:
PARZ_TAB:
...
...
...
TMP_A:
TMP_B:
TMP_IA:
TMP_IB:
BSEG AT 20h
DBIT 1
DBIT 1
; absolutny segment bitowy od 20h
; bit o adresie absolutnym
CSEG AT 100h
DB 00h
DB 01h
DB 01h
DB 00h
;
;
;
;
;
DB 01h
DB 00h
; FEh
; FFh
DSEG AT 40h
DS 2
DS 4
; absolutny segment danych od 40h
; słowo danych o adresie absolutnym
ISEG AT 80h
; absolutny segment danych w pamięci
; adresowanej pośrednio od 80h
DS 2
DS 4
XSEG AT 1000h
NAZWA1:
NAZWA2:
WERSJA:
DS 25
DS 25
DS 25
;
;
;
;
absolutny segment kodu od 100h
parzystość dla 00h
01h
02h
03h
absolutny segment w zewnętrznej
pamięci danych od 1000h
dana w pamięci zewnętrznej o adresie
absolutnym
4
NOWA_FLAGA:
BSEG
DBIT 1
; dalsza część absolutnego
; segmentu bitowego
Segment domyślny
Domyślnie asembler A51 przyjmuje, że wybrany jest segment kodu i na początku procesu asemblacji
modułu źródłowego inicjalizuje licznik położenia wartością 0000H. Umożliwia to tworzenie programu bez
określania żadnej dyrektywy dla segmentu relokowalnego, czy też absolutnego.
Definicje symboli
Dyrektywy definiujące symbole umożliwiają tworzenie symboli, które mogą być używane do
reprezentacji rejestrów, liczb i adresów.
Symbole definiowane przez te dyrektywy nie mogą być wcześniej zdefiniowane i nie mogą być
definiowane ponownie. Wyjątkiem od tych reguł jest dyrektywa SET.
EQU, SET
Dyrektywy EQU i SET przyporządkowują wartości numeryczne lub symbole rejestrów do
wyspecyfikowanych nazw symbolicznych. Symbole zdefiniowane za pomocą dyrektywy EQU nie mogą być
wcześniej zdefiniowane, a także nie mogą być później redefiniowane. Dyrektywa SET umożliwia późniejszą
redefinicję symbolu. Instrukcje wymagające dyrektyw EQU i SET maja następujący format:
symbol
symbol
symbol
symbol
EQU
EQU
SET
SET
wyrażenie
rejestr
wyrażenie
rejestr
symbol
nazwa symboliczna do zdefiniowania. Wyrażenie lub rejestr wyspecyfikowany w dyrektywach
EQU lub SET będą wstawiane przy każdym wystąpieniu symbolu w bieżącym programie
asemblerowym.
wyrażenie
wyrażenie numeryczne, które nie zawiera odniesień w przód lub proste relokowalne wyrażenia.
rejestr
jedna z nazw rejestrów, np.: A, R0, R1, R2, R3, R4, R5, R6 lub R7.
Symbole zdefiniowane za pomocą dyrektywy EQU lub SET mogą być użyte wszędzie w operandach,
wyrażeniach lub adresach. Natomiast symbole, które są zdefiniowane jako nazwy rejestrów, mogą być użyte
wszędzie, gdzie dopuszczalne jest użycie rejestrów.
Nie można użyć dyrektywy SET, jeśli symbol został wcześniej zdefiniowany za pomocą dyrektywy
EQU i odwrotnie.
Przykłady:
GRANICA
ROZMIAR
SERIAL
ACCU
LICZNIK1
WARTOSC
WARTOSC
LICZNIK2
TEMP
TEMP
EQU
EQU
EQU
EQU
EQU
SET
SET
SET
SET
SET
1200
GRANICA – 200 + 'A'
SBUF
A
R5
100
WARTOSC / 2
R1
LICZNIK2
WARTOSC * WARTOSC
BIT, CODE, DATA, IDATA, XDATA
5
Dyrektywy BIT, CODE, DATA, IDATA, XDATA określają przyporządkowuję określonemu
symbolowi wartość adresu. Symbole zdefiniowane za pomocą dyrektyw BIT, CODE, DATA, IDATA,
XDATA nie mogą być zmieniane ani redefiniowane. Dyrektywy te mają następujący format:
symbol
symbol
symbol
symbol
symbol
BIT
CODE
DATA
IDATA
XDATA
adres_bitu
adres_kodur
adres_danej
adres_idanej
adres_xdanej
symbol
definiowana nazwa symboliczna. Może być ona używana w każdym miejscu, gdzie wymagany
jest adres w pamięci wyspecyfikowanego typu.
adres_bitu
jest adresem bitu z wewnętrznej pamięci danych w przestrzeni o adresach z zakresu 20H .. 2FH
adresowanej bitowo lub adresem bitu rejestru SFR adresowanego bitowo.
adres_kodu
jest adresem kodu z zakresu 0000H .. FFFFH.
adres_danej
jest adresem rejestru SFR z zakresu adresów 80H .. FFH lub adresem z wewnętrznej pamięci
danych z zakresu 0 .. 7FH.
adres_idanej
jest adresem wewnętrznej pamięci danych adresowanej pośrednio z zakresu 00H .. FFH.
adres_xdanej
jest adresem zewnętrznej pamięci danych z zakresu 0 .. 65535.
Przykłady
DATA_SEG
SEGMENT
RSEG
BIT
DATA_SEG
CTRL:
ALARM
SHUT
ENABLE_FLAG
DONE_FLAG
RESTART
INTVEC_0
INTVEC_1
INTVEC_2
SERBUF
RESULT
RESULT2
BUFFER
BUF_LEN
BUF_END
DS
BIT
BIT
BIT
BIT
CODE
CODE
CODE
CODE
DATA
DATA
DATA
IDATA
EQU
IDATA
XSEG1
SEGMENT
RSEG
DTIM:
TIME
DATE
DS
6
XDATA DTIM + 0
XDATA DTIM + 3
;
;
;
;
;
;
;
segment relokowalny adresowany
bitowo
1–bajtowa zmienna (CTRL)
bit w relokowalnym bajcie
następny bit
bezwzględny bit
bezwzględny bit
1
CTRL.0
ALARM+1
60H
24H.2
00H
RESTART + 3
RESTART + 0BH
RESTART + 1BH
SBUF
; redefinicja bufora SBUF
40H
RESULT + 2
60H
20H
BUFFER + BUF_LEN – 1
XDATA
XSEG1
;rezerwuje 6–bajtów dla DTIM
Inicjalizacja pamięci
6
Dyrektywy inicjalizujące pamięć są używane do inicjalizacji przestrzeni kodu lub stałych jednostkami
danych o długości bajta lub słowa. Obraz pamięci rozpoczyna się w punkcie wskazywanym przez bieżącą
wartość licznika położenia w obecnie aktywnym segmencie.
DB
Dyrektywa DB inicjalizuje pamięć kodu 8-bitowymi wartościami bajtów. Dyrektywa DB ma
następujący format:
etykieta:
DB
wyrażenie, wyrażenie ...
etykieta
symbol, który określa adres inicjowanej pamięci.
wyrażenie
wartość bajtowa. Każde wyrażenie może być symbolem, ciągiem znaków lub wyrażeniem.
Dyrektywa DB może być umieszczana tylko wewnątrz segmentu kodu programu.
Przykłady:
REQUEST:
TABLE:
ZERO:
CASE_TAB:
DB
DB
DB
DB
'PRESS ANY KEY TO CONTINUE', 0
0,1,8,'A','0', LOW(TABLE),';'
0, ''''
LOW(REQUEST), LOW(TABLE), LOW(ZERO)
DW
Dyrektywa DW inicjalizuje pamięć kodu 16-bitowymi słowami. Dyrektywa DW ma następujący
format:
etykieta:
DW
wyrażenie, wyrażenie ...
etykieta
symbol, który określa adres inicjowanej pamięci.
wyrażenie
wartość dwubajtowa. Każde wyrażenie może być symbolem, ciągiem znaków lub wyrażeniem.
Dyrektywa DW może być umieszczana tylko wewnątrz segmentu kodu programu.
Przykłady:
TABLE:
CASE_TAB:
DW
DW
DW
1234, 233AH, ‘QR’
CASE0, CASE1, CASE2, CASE3, CASE4
$
Rezerwacja pamięci
Dyrektywy rezerwacji pamięci są używane do rezerwacji przestrzeni jednostkami o długości bajta lub
słowa. Rezerwacja tej przestrzeni rozpoczyna się w punkcie wskazywanym przez bieżącą wartość licznika
położenia w obecnie aktywnym segmencie.
DBIT
Dyrektywa DBIT rezerwuje przestrzeń w segmencie danych adresowanych bitowo. Dyrektywa DBIT
ma następujący format:
etykieta
DBIT
wyrażenie
7
etykieta
symbol, który określa adres rezerwowanej pamięci. Etykieta jest symbolem typu BIT i pobiera
bieżącą wartość adresu oraz klasę pamięci aktywnego segmentu. Etykieta ta może być użyta
tam, gdzie użycie segmentu tego typu jest dopuszczalne.
wyrażenie
liczba rezerwowanych bitów. Wyrażenie nie może zawierać odniesień w przód, symboli
relokowalnych lub zewnętrznych symboli.
Dyrektywa DBIT rezerwuje przestrzeń w segmencie adresowanym bitowo rozpoczynając od bieżącego
adresu.
Przykłady:
ON_FLAG:
OFF_FLAG:
DBIT
DBIT
1
2
; rezerwuje 1 bit
; rezerwuje 2 kolejne bity
DS
Dyrektywa DS rezerwuje określoną liczbę bajtów w przestrzeni pamięci danych. Dyrektywa DS ma
następujący format:
etykieta:
DS
wyrażenie
etykieta
symbol, który określa adres rezerwowanej pamięci. Etykieta pobiera bieżącą wartość adresu i
klasę pamięci aktywnego segmentu. Etykieta ta może być użyta tam, gdzie użycie segmentu
tego typu jest dopuszczalne.
wyrażenie
liczba rezerwowanych bitów. Wyrażenie nie może zawierać odniesień w przód, symboli
relokowalnych lub zewnętrznych symboli.
Dyrektywa DS rezerwuje przestrzeń w bieżącym segmencie rozpoczynając od bieżącego adresu.
Przykłady:
GAP:
TIME:
DS
DS
DS
(($ + 16) AND 0FFF0H) – $
20
8
Łączenie programów
Dyrektywy związane z łączeniem (linkowaniem) programów umożliwiają wzajemną komunikację
oddzielnych modułów asemblerowych przez ich nazewnictwo i
zezwolenie na używanie symboli
zdefiniowanych wewnątrz innych modułów.
NAME
Dyrektywa NAME określa nazwę, która będzie użyta dla modułu obiektowego wygenerowanego dla
bieżącego programu. Nazwa pliku obiektowego nie jest nazwą modułu obiektowego. Nazwa modułu
obiektowego jest wbudowana w plik obiektowy. Dyrektywa NAME ma następujący format:
NAME
nazwa_modułu
nazwa_modułu
nazwa, która będzie użyta do oznaczenia modułu obiektowego. Nie może ona
przekroczyć 40 znaków. Przy określaniu nazwy modułu należy przestrzegać zasad
określonych dla nazw symbolicznych.
W pliku programu może być określona tylko jedna dyrektywa NAME. Jeśli dyrektywa ta nie zostanie
określona, nazwą modułu obiektowego będzie nazwa pliku źródłowego bez rozszerzenia.
8
Przykład:
NAME
MOJ_MODUL
PUBLIC
Dyrektywa PUBLIC wylicza symbole, które są zdefiniowane w bieżącym module, a których użycie
dopuszcza się w innych modułach. W efekcie daje więc ona dostęp z zewnętrznych modułów do danego modułu.
Dyrektywa PUBLIC ma następujący format:
PUBLIC
symbol, symbol ...
symbol
musi być symbolem, który został zdefiniowany w danym pliku źródłowym.
Odniesienia w tył do nazw symboli są dopuszczalne. Wszystkie nazwy symboliczne,
za wyjątkiem symboli rejestrów i segmentów, mogą być specyfikowane w dyrektywie
PUBLIC. Przy wprowadzaniu kilku symboli należy rozdzielać je przecinkami.
Jeśli symbole publiczne mają być użyte w innym pliku źródłowym, należy użyć w nim dyrektywy
EXTRN określającej, że symbole są zadeklarowane w innym module obiektowym.
Przykład:
PUBLIC
PUBLIC
PUT_CLRF, PUT_STRING, PUT_EOS
ASCII_BIN, BIN_ASCII
EXTRN
Dyrektywa EXTRN wylicza symbole (związane z danym modułem źródłowym), które są w
rzeczywistości zadeklarowane w innym module. Format dyrektywy EXTRN ma następującą postać:
EXTRN
klasa
klasa
(symbol, symbol ...)
jest klasą pamięci (BIT, CODE, DATA, IDATA, XDATA), w której został
zdefiniowany symbol.
jest nazwą zewnętrznego symbolu.
symbol
Dyrektywa EXTRN może występować w dowolnym miejscu programu źródłowego. Przy
wprowadzaniu kilku symboli należy rozdzielić je przecinkami i umieścić w nawiasach za informacją o klasie.
Nazwy symboliczne, które są określane w dyrektywie EXTRN, muszą być wcześniej określone jako
symbole publiczne przy pomocy dyrektywy PUBLIC w pliku źródłowym, w którym zostały one zadeklarowane.
Linker rozpoznaje wszystkie symbole zewnętrzne w czasie linkowania i weryfikuje, czy klasa symbolu
(określona w dyrektywie EXTRN i PUBLIC) zgadza się.
Przykład:
EXTRN
EXTRN
CODE
CODE
(PUT_CLRF, PUT_STRING, PUT_EOS)
(ASCII_BIN, BIN_ASCII)
Przełączanie adresów
Poniższe dyrektywy umożliwiają sterowanie licznikiem położenia lub symbolami rejestrów
absolutnych.
ORG
Dyrektywa ORG jest używana do zmiany obecnie aktywnego segmentu i ustalenia nowego początku
dla dalszych instrukcji. Dyrektywa ORG ma następujący format:
9
ORG
wyrażenie
wyrażenie
musi być wyrażeniem absolutnym lub relokowalnym w prosty sposób bez odniesień w
przód. Mogą być używane tylko adresy absolutne lub wartości symboliczne z
bieżącego segmentu.
Kiedy zostanie napotkana instrukcja ORG, asembler oblicza wartość wyrażenia i ustala lokalizację dla
bieżącego segmentu. Jeśli instrukcja ORG wystąpi w segmencie absolutnym, lokalizacja jest jako absolutna
wartość adresu. Jeśli instrukcja ORG wystąpi w segmencie relokowalnym, to lokalizacja określona wyrażeniem
jest ustalana jako offset adresu.
Przykłady:
ORG
ORG
ORG
ORG
100H
RESTART
EXIT1
($ + 16) AND 0FFF0H
USING
Dyrektywa USING określa, który bank rejestrów ma być użyty dla kodowania rejestrów AR0 do AR7.
Dyrektyw ta jest określana jak poniżej:
USING
wyrażenie
wyrażenie
jest numerem banku rejestrów, który jest wartością z zakresu 0 do 3.
Dyrektywa USING nie generuje żadnego kodu zmieniającego bank rejestrów, dlatego należy się
upewnić, że wybrano właściwy bank rejestrów. Do zmiany banku rejestrów można użyć poniższy przykład, w
którym wybrano bank 2 rejestrów:
PUSH PSW
MOV PSW,#(2 SHL 3)
...
...
...
...
...
...
POP PSW
;zapamiętanie PSW/banku rejestrów
;wybór banku 2 rejestrów
;inne instrukcje
;przywrócenie PSW/banku rejestrów
Bank rejestrów wybrany przez dyrektywę USING jest zaznaczany w pliku *.obj, a przestrzeń pamięci
wymagana przez ten bank rejestrów rezerwowana przez linker.
Wartości AR0 do AR7 są obliczane jako absolutne adresy rejestrów R0 do R7 w banku rejestrów
określonym przez dyrektywę USING. Niektóre instrukcje jak PUSH i POP umożliwiają tylko użycie
absolutnych adresów rejestrów. Domyślnie do symboli AR0 do AR7 przypisane są rejestry banku 0.
UWAGA. Kiedy dyrektywa EQU jest użyta do zdefiniowania symboli dla ARn, adres rejestru Rn jest obliczany
w momencie definiowania symbolu, a nie w miejscu jego użycia. Kiedy dyrektywa USING zmienia później
bank rejestrów, zdefiniowany symbol nie ma właściwego adresu rejestru ARn i generowany kod jest
prawdopodobnie niepoprawny.
10
Inne dyrektywy
END
Dyrektywa END określa koniec modułu asemblerowego. Tekst, który występuje za dyrektywą END
jest ignorowany. Dyrektywa END jest wymagana w każdym pliku asemblerowym.
Przykład:
END
Symbole
Symbol jest nazwą, która jest definiowana w celu reprezentacji wartości, bloku tekstu, adresu lub nazwy
rejestru. Symbole mogą być również używane do reprezentowania stałych numerycznych i wyrażeń.
Nazwy symboliczne
Symbole mogą zawierać do 31 znaków z listy znaków podanej poniżej:
A-Z, a-z, 0-9, _, ?
Nazwa symboliczna może rozpoczynać się od dowolnego z tych znaków, za wyjątkiem cyfr 0-9.
Symbole mogą być definiowane w wielu różnych przypadkach. Można definiować symbol do
reprezentacji wyrażeń:
NUMER
PRAWDA
FALSZ
EQU
SET
SET
5
1
0
etykiet w programie
ETYKIETA_1: DJNZ R0, ETYKIETA_1
lub odniesień do adresu zmiennej
BUFOR_SZER DATA
99H
Symbole są używane w całym programie asemblerowym. Nazwa symboliczna jest łatwiejsza do
zrozumienia i zapamiętania, niż adres lub stała numeryczna.
Etykiety
Etykieta definiuje „miejsce” (adres) w przestrzeni programu lub danych. Wszystkie zasady dotyczące
tworzenia nazw symbolicznych mają zastosowanie przy tworzeniu etykiet. Podczas ich definiowania, etykieta
musi być pierwszym polem tekstowym w linii. Może być ona poprzedzona znakami tabulacji i/lub spacji. Znak
dwukropka (:) musi wystąpić bezpośrednio po nazwie symbolicznej etykiety, aby można było rozpoznać, że jest
to etykieta. W linii może być zdefiniowana tylko jedna etykieta. Na przykład:
ETYK_1:
ETYK_2:
LICZBY:
KOPIUJ:
DS
2
DB
27, 33, ‘ZNAKI’, 0
MOV R6, #12H
; etykieta na siebie samą
; etykieta na stałe
; etykieta na instrukcję w programie
W powyższym przykładzie, ETYK_1, ETYK_2, LICZBY i KOPIUJ są etykietami.
Etykieta może odnosić się do kodu programu, przestrzeni zmiennych w wewnętrznej lub zewnętrznej
pamięci danych lub stałej przechowywanej w przestrzeni programu. Przy definiowaniu etykiety przejmuje ona
bieżącą wartość licznika położenia danego segmentu.
11
Etykieta jest również używana w instrukcjach skoków, do wskazania miejsca (adresu) przeznaczenia.
Instrukcja występująca za etykieta jest tą instrukcją, która będzie wykonywana po skoku pod adres programu
wskazany etykietą.
W programie można nie tylko wykonywać skoki pod określone etykiety, lecz także wywoływać
podprogramy określone etykietą. W takim przypadku wykonywany jest kod znajdujący się za etykieta, aż do
napotkania instrukcji asemblerowej RET.
Wyrażenia i operatory
Operand (argument operacji) może być stałą numeryczną, nazwą symboliczną, ciągiem znakowym lub
wyrażeniem.
Operatory są używane do łączenia i porównywania operandów wewnątrz programu asemblerowego.
Operatory nie są instrukcjami języka asemblera, ani nie generują kodu asemblerowego. Reprezentują one
operacje, które są szacowane w czasie asemblacji programu. Dlatego operatory mogą obejmować tylko
obliczenia wartości, które są znane podczas asemblacji programu.
Wyrażenie jest połączeniem liczb, ciągów znakowych symboli i operatorów, które podlega zamianie na
16-bitowaą wartość binarną. Wyrażenia są szacowane podczas asemblacji i dlatego mogą być używane do
obliczania wartości, które w innym przypadku byłyby trudne do wyznaczenia wcześniej.
Liczby
Liczby mogą być określane jako wartości: szesnastkowe, dziesiętne, ósemkowe lub dwójkowe.
Podstawa liczby jest określana przez ostatni znak w liczbie. Liczba, która jest zapisana bez specyfikatora
podstawy, jest interpretowana jako liczba dziesiętna.
Poniższa tabela pokazuje specyfikatory podstawy liczb, przyrostki i przykłady.
Podstawa
Szesnastkowa
Dziesiętna
Ósemkowa
Dwójkowa
Przyrostek
H, h
D, d
O, o, Q, q
B, b
Dopuszczalne znaki
0-9, A-F, a-f
0-9
0-7
0i1
Przykłady
1234H 0A0F0H 0F0H 1a24h 34fcH
123 23D 2092d
172q 34Q 345o 44O
1001011b 10011B
Pierwszym znakiem liczby musi być zawsze cyfra z zakresu 0 do 9. Liczby szesnastkowe,
których zapis wartości zaczyna się od litery muszą być poprzedzone cyfrą 0.
Znaki
Asembler A51dopuszcza użycie znaków ASCII w wyrażeniach do tworzenia wartości numerycznych.
Wyrażenie takie może składać się maksymalnie z dwóch znaków objętych pojedynczym apostrofem (‘).
Umieszczenie większej ilości znaków spowoduje wygenerowanie błędu podczas asemblacji. Poniżej
przedstawiono kilka przykładów:
‘A’
‘AB’
‘a’
‘ab’
‘’
‘abc’
jest przeliczane na wartość
jest przeliczane na wartość
jest przeliczane na wartość
jest przeliczane na wartość
ciąg pusty jest przeliczany
generuje BŁĄD
0041H
4142H
0061H
6162H
na wartość 0000H
Znaki można również używać w każdym miejscu programu, gdzie wymagane są dane bezpośrednie.
LITERA_A
EQU
‘A’
TEST:
MOV @R0,#’F’
SUBB A,#’0’
12
Ciągi znaków
Ciągi znaków mogą być używane w połączeniu z dyrektywą DB do definiowania wiadomości uzywanych w
programie. Taki ciąg musi być objęty pojedynczym apostrofem (‘). Na przykład:
WIADOMOSC
DB
‘Wcisnij dowolny klawisz, aby kotynuowac.’
generuje szesnastkowe dane (57H, 63H, 69H, 73H, 6EH 69H 6AH, ..., 61H, 63H, 2EH) rozpoczynając od adresu
oznaczonego etykietą WIADOMOSC.
Ciągi i dane liczbowe mogą być łączone ze sobą w jednej linii. Na przykład:
EOL_WIAD
DB
‘Koniec linii’, 00H
dodaje wartość 00H na koniec ciągu ‘Koniec linii’.
Aby wstawić w definiowanym ciągu znakowym znak pojedynczego apostrofu, należy wyspecyfikować
go dwukrotnie pod rząd.
MSG
DB
‘ISN’’T A QUOTE REQUIRED HERE?’
13
;-----------------------------------------------------------------------------; Source code template for A251/A51 assembler modules.
; Copyright (c) 1995-1996 KEIL Software, Inc.
;-----------------------------------------------------------------------------$NOMOD51
; dezaktywacja predefiniowanych rejestrów 8051
$INCLUDE (REG52.INC)
; dołączenie pliku definiującego rejestry CPU
; (tutaj 8052)
;-----------------------------------------------------------------------------; Zmień nazwy napisane małymi literami, aby dostosować wzór do własnych
; potrzeb.
;
; Ten szablon pokazuje idee użycia asemblera A51. Nie jest wymagane,
; aby każdy moduł tworzyć w ten sposób – to jest tylko przykład.
;
; Wszystkie wpisy za wyjątkiem dyrektywy END na końcu pliku są opcjonalne.
;
; Jeśli użyjesz tego szablonu upewnij się, że wszystkie nieużywane
; deklaracje segmentów jak również zmienne i instrukcje asemblerowe
; zostały usunięte.
;
; Ten plik nie pokazuje wszystkich możliwości asemblera A51.
; Po więcej informacji należy odnieść się do ”User's Guide”.
;-----------------------------------------------------------------------------;-----------------------------------------------------------------------------; Nazwa modułu (opcjonalna)
;-----------------------------------------------------------------------------NAME
module_name
;-----------------------------------------------------------------------------; W tym miejscu można importować symbole z innych modułów.
;-----------------------------------------------------------------------------EXTRN CODE
(code_symbol)
; Mogą tu wystąpić nazwy podprogramów
; zadeklarowane w segmentach CODE lub z
; dyrektywą CODE.
EXTRN DATA
(data_symbol)
; Mogą tu wystąpić wszystkie symbole
; zadeklarowane w segmentach DATA lub z
; dyrektywą DATA.
EXTRN BIT
(bit_symbol)
; Mogą tu wystąpić wszystkie symbole
; zadeklarowane w segmentach BIT lub z
; dyrektywą BIT.
EXTRN XDATA (xdata_symbol)
; Mogą tu wystąpić wszystkie symbole
; zadeklarowane w segmentach XDATA lub z
; dyrektywą XDATA.
EXTRN NUMBER (typeless_symbol)
; Mogą tu wystąpić wszystkie symbole
; zadeklarowane z dyrektywą EQU lub SET.
;-----------------------------------------------------------------------------; Instrukcja EXTRN może zawierać więcej niż jeden symbol.
;-----------------------------------------------------------------------------EXTRN CODE (sub_routine1, sub_routine2), DATA (variable_1)
;-----------------------------------------------------------------------------; Wymuszenie nowej strony w pliku listingu.
;-----------------------------------------------------------------------------$EJECT
1
;-----------------------------------------------------------------------------; W tym miejscu można eksportować symbole do innych modułów
;-----------------------------------------------------------------------------PUBLIC data_variable
PUBLIC code_entry
PUBLIC typeless_number
PUBLIC xdata_variable
PUBLIC bit_variable
;-----------------------------------------------------------------------------; Instrukcja PUBLIC może zawierać więcej niż jeden symbol.
;-----------------------------------------------------------------------------PUBLIC data_variable1, code_table, typeless_num1, xdata_variable1
;-----------------------------------------------------------------------------; Umieszczenie segmentu stosu STACK w głównym module.
;-----------------------------------------------------------------------------?STACK
SEGMENT
IDATA ; ?STACK jest umieszczane w pamięci IDATA.
RSEG
?STACK
; przejście do segmentu ?STACK.
DS
5
; rezerwacja przestrzeni dla stosu
; w tym wypadku 5 bajtów.
$EJECT
;-----------------------------------------------------------------------------; Deklaracje segmentów i zmiennych.
;-----------------------------------------------------------------------------;-----------------------------------------------------------------------------; Segment DATA — rezerwuje przestrzeń w pamięci DATA. Należy go skasować, gdy
; nie jest używany.
;-----------------------------------------------------------------------------data_s_name SEGMENT
DATA
; segment dla DATA RAM.
RSEG
data_s_name
; przejście do segmentu data
data_variable:
DS
1
; rezerwuje 1 bajt dla data_variable
data_variable1:
DS
2
; rezerwuje 2 bajty dla data_variable1
;-----------------------------------------------------------------------------; Segment XDATA - rezerwuje przestrzeń w pamięci XDATA. Należy go skasować, gdy
; nie jest używany.
;-----------------------------------------------------------------------------xdata_s_name SEGMENT
XDATA
; segment dla XDATA RAM
RSEG
xdata_s_name
; przejście do segmentu xdata
xdata_variable:
DS
1
; rezerwuje 1 bajt dla xdata_variable
xdata_array:
DS
500
; rezerwuje 500 bajtów dla xdata_array
;-----------------------------------------------------------------------------; Segment absolutny w XDATA – rezerwuje przestrzeń w pamięci XDATA od
; adresu absolutnego. Należy go skasować, gdy nie jest używany.
;-----------------------------------------------------------------------------XSEG AT 8000H
; przełączenie na segment absolutny
; w pamięci XDATA od adresu 8000H
XIO:
DS
1
; rezerwacja 1 bajta dla XIO
XCONFIG:
DS
1
; rezerwacja 1 bajta dla XCONFIG
;-----------------------------------------------------------------------------; Segment BIT – rezerwuje przestrzeń w pamięci BIT. Należy go skasować, gdy nie
; jest używany.
;-----------------------------------------------------------------------------bit_s_name
SEGMENT
BIT
; segment dla BIT RAM.
RSEG
bit_s_name
; przejście do segmentu bitowego
bit_variable:
DBIT
1
; rezerwuje 1 bit dla bit_variable
bit_variable1:
DBIT
4
; rezerwuje 4 bity dla bit_variable1
2
;-----------------------------------------------------------------------------; Deklaracja stałych (bez określonego typu) numerycznych.
;-----------------------------------------------------------------------------typeless_number
EQU
0DH
; przypisuje 0D hex
typeless_num1
EQU
typeless_number-8
; oblicza typeless_num1
$EJECT
;-----------------------------------------------------------------------------; Powoduje skok LJMP na start.
; Można użyć tego stylu przy wykorzystywaniu przerwań.
;-----------------------------------------------------------------------------CSEG
AT 0
; segment absolutny od adresu 0
LJMP
start
; skok na start
;-----------------------------------------------------------------------------; W celu dodania podprogramu obsługi przerwania, należy umieścić
; instrukcję LJMP do tego podprogramu pod odpowiednim adresem wektora
; przerwań.
;-----------------------------------------------------------------------------CSEG
AT 0BH
; 0BH jest adresem wektora przerwania
; dla licznika 0
LJMP
timer0int
;-----------------------------------------------------------------------------; Segment CODE – rezerwuje przestrzeń w pamięci CODE dla instrukcji
; asemblerowych.
;-----------------------------------------------------------------------------code_seg_nameSEGMENT
CODE
RSEG
code_seg_name; przełączenie na segment code
USING 0
start:
MOV
; użycie banku 0 rejestrów dla poniższego
; kodu programu
SP,#?STACK-1 ; przypisanie początku stosu do rejestru SP
;-----------------------------------------------------------------------------; Tutaj umieść swój program asemblerowy. Poniższy kod nie jest funkcjonalny.
;-----------------------------------------------------------------------------ORL
IE,#82H
; aktywacja systemu przerwań (licznik 0)
SETB
TR0
; aktywacja licznika 0
repeat_label:MOV
A,data_symbol
ADD
A,#typeless_symbol
CALL
code_symbol
MOV
DPTR,#xdata_symbol
MOVX
A,@DPTR
MOV
R1,A
PUSH
AR1
CALL
sub_routine1
POP
AR1
ADD
A,R1
JMP
repeat_label
code_entry:
CALL
RET
code_symbol
code_table:
DW
DW
DB
DB
repeat_label
code_entry
typeless_number
0
$EJECT
3
;-----------------------------------------------------------------------------; Przydziel każdemu podprogramowi obsługi przerwania jego własny segment kodu.
;-----------------------------------------------------------------------------int0_code_segSEGMENT
CODE
; segment dla podprogramu przerwania
RSEG
int0_code_seg
; przełączenie na segment code
USING 1
; bank rejestrów dla podprogramu przerwania
timer0int:
PUSH
MOV
PUSH
MOV
MOV
MOVX
ADD
MOV
CLR
ADD
MOV
POP
POP
RETI
PSW
PSW,#08H
; bank 1 rejestrów
ACC
R1,data_variable
DPTR,#xdata_variable
A,@DPTR
A,R1
data_variable1,A
A
A,#0
data_variable1+1,A
ACC
PSW
;-----------------------------------------------------------------------------; Dyrektywa END jest zawsze wymagana.
;-----------------------------------------------------------------------------END
; Koniec pliku
4
NAME PRZETWORNIK_CA
ADRES_CA
EQU 8000H
;definicja stałej o wartości 8000H
BIT_SEG
SEGMENT BIT
RSEG BIT_SEG
DBIT 1
;definicja segmentu relokowalnego
;w pamięci adresowanej bitowo
;zmienna o rozmiarze 1-go bita
ZNACZNIK:
ZMIENNE_SEG SEGMENT DATA
;definicja segmentu relokowalnego
RSEG ZMIENNE_SEG ;w pamięci adresowanej bezpośrednio
WARTOSC:
DS 1
;zmienna o rozmiarze 1-go bajta
START:
CSEG AT 0
LJMP START
;absolutny segment kodu od adresu 0
;skok instrukcji oznaczonej etykietą START
ORG 0BH
LJMP T0_INT
;absolutny segment kodu od adresu 0BH
;skok do instrukcji oznaczonej etykietą T0_INT
ORG 23H
LJMP SER_INT
;absolutny segment kodu od adresu 23B
;skok do instrukcji oznaczonej etykietą SER_INT
MOV
MOV
MOV
MOV
MOV
MOV
MOV
MOV
SETB
;początek prog. Głównego; ustawienie wskaźnika stosu
;T0 – tryb 0, T1 – tryb 2
;wartość początkowa licznika T0; przerwanie będzie
;wyzwalane co 50ms dla rezonatora 12MHz
;wartość początkowa licznika T1 taktującego port
;szeregowy
;tryb 1 portu szeregowego
;wartość początkowa zmiennej WARTOSC
;wartość początkowa znacznika ZNACZNIK
SP,#60H
TMOD, #21H
TL0, #0AFH
TH0, #3CH
TL1, #0FDH
TH1, #0FDH
SCON, #50H
WARTOSC, #0
ZNACZNIK
1
SETB
SETB
MOV
SJMP
TRO
TR1
IE,#10010010B
$
;uruchomienie licznika T0
;uruchomienie licznika T1
;aktywacja przerwań od T0 i portu szeregowego
;koniec programu głównego, skok na siebie
T0_INTSEG
SEGMENT CODE
;relokowalny segment kodu dla podprogramu obsługi
RSEG T0_INT_SEG ;przerwania od licznika T0
T0_INT: ORL TH0, #0AFH
;przepisanie początkowych wartości
MOV TH0, #3CH
;do rejestrów licznika
JNB ZNACZNIK, OPUSC_T ; jeśli ZNACZNIK różny od 1 to skacz __
PUSH A
;zapamiętanie zawartości akumulatora na stosie
MOV A, WARTOSC
MOV DPTR, #ADRES_CA ;zapis adresu przetwornika C/A do rejestru DPTR
MOVX @DPTR, A
;wysłanie wartości do przetwornika C/A
INC WARTOSC
;inkrementacja zmiennej WARTOSC
POP A
;ściągnięcie ze stosu wartości akumulatora
OPOSC_T: RETI
;__ tutaj; koniec podprogramu obsługi przerwania
SER_INT_SEG SEGMENT CODE
RSEG SER_INT_SEG
SER_INT: PUSH A
CLR RI
MOV A, SBUF
CJNE A, #10, OPUSC_S
CPL ZNACZNIK
OPUSC_S: POP A
RETI
;relokowalny segment kodu dla podprogramu obsługi
;przerwania od portu szeregowego
;zapamiętanie zawartości akumulatora na stosie
;zerowanie znacznika odebrania znaku
;odczyt bufora portu szeregowego
;gdy odebrana wartość różna od 10, to ...
;negacja bitu ZNACZNIK
;... skacze tutaj
;koniec podprogramu obsługi przerwania
END
;koniec programu
2

Podobne dokumenty