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