1. 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, oraz nie wpływają bezpośrednio na zawartość kodu programu. Poniższa tabela pokazuje najczęściej wykorzystywane dyrektywy asemblerowe zaimplementowane w omawianym asemblerze firmy Keil. Dyrektywa Format Opis Segmenty CSEG CSEG [AT adres_absolutny] Definicja segmentu absolutnego w pamięci kodu BSEG BSEG [AT adres_absolutny] Definicja segmentu absolutnego w pamięci danych adresowanej bitowo DSEG DSEG [AT adres_absolutny] Definicja segmentu absolutnego w wewnętrznej pamięci danych adresowanej bezpośrednio ISEG ISEG [AT adres_absolutny] Definicja segmentu absolutnego w wewnętrznej pamięci danych adresowanej pośrednio XSEG XSEG [AT adres_absolutny] Definicja segmentu absolutnego w zewnętrznej pamięci danych Definicje symboli EQU symbol EQU Trwałe przypisanie wartości symbolowi SET symbol SET Czasowe przypisanie wartości symbolowi BIT symbol BIT adres_bitu Definicja adresu bitu w bitowej przestrzeni danych CODE symbol CODE adres_kodu Przypisanie symbolowi określonego adresu w przestrzeni pamięci kodu DATA symbol DATA adres_danej Przypisanie symbolowi określonego adresu z wewnętrznej przestrzeni danych adresowanej bezpośrednio IDATA symbol IDATA adres_danej Przypisanie symbolowi określonego adresu z wewnętrznej przestrzeni danych adresowanej pośrednio XDATA symbol XDATA adres_danej Przypisanie symbolowi określonego adresu z zewnętrznej przestrzeni danych Inicjalizacja pamięci kodu DB [etykieta:] DB [,,] Tworzy listę wartości, każda o rozmiarze bajta DW [etykieta:] DW [,,] Tworzy listę wartości, każda o rozmiarze słowa Rezerwacja pamięci danych DBIT [etykieta:] DBIT Rezerwuje w pamięci określoną m liczbę bitów DS [etykieta:] DS Rezerwuje w pamięci określoną m liczbę bajtów Przełączanie adresów Określa umiejscowienie bieżącego segmentu USING USING Określa predefiniowany adres rejestru symbolicznego i rezerwuje przestrzeń dla określonego banku rejestrów Inne NAME NAME nazwa_modułu Określa nazwę bieżącego modułu END END Wskazuje koniec programu 1
2. 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, jak: pamięć kodu programu, wewnętrzna pamięć danych adresowana bitowo, bezpośrednio lub pośrednio, zewnętrzna pamięć danych. Segmenty są więc używane do umiejscowienia kodu programu, stałych i zmiennych w tych przestrzeniach. 2.1 Licznik położenia Podczas swojej pracy program asemblujący (asembler) przyporządkowuje każdemu segmentowi 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. Jego wartość jest zmieniana po przeanalizowaniu danej instrukcji o wartość związaną z jej implementacją w danym segmencie. 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 ustala 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ę, 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. 2.2 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ą tworzone przy użyciu dyrektyw: CSEG, BSEG, DSEG, ISEG i XSEG. Wymienione dyrektywy 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 od określonego adresu. Po resecie mikrokontroler rozpoczyna wykonywanie programu od adresu 0. Jeśli właściwy program nie zaczyna się od tego adresu, to pod nim musi być umieszczona co najmniej jedna instrukcja, która przekieruje wykonywanie programu pod właściwy adres. 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 w dalszej części pamięci kodu. CSEG AT 0 RESET_VECT: LJMP STARTUP 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ą adres bezwzględny w odpowiednim segmencie programu, od którego będą umieszczane instrukcje występujące po tej dyrektywie. Adres segmentu jest więc ustalany przez programistę już w chwili pisania programu. Omawiane dyrektywy mają następujący format: BSEG AT adres ;definiuje bezwzględny adres w segmencie BIT CSEG AT adres ;definiuje bezwzględny adres w segmencie CODE DSEG AT adres ;definiuje bezwzględny adres w segmencie DATA ISEG AT adres ;definiuje bezwzględny adres w segmencie XDATA XSEG AT adres ;definiuje bezwzględny adres w segmencie IDATA 2
adres 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ć m, które po obliczeniu daje konkretną wartość. Dyrektywy BSEG, CSEG, DSEG, ISEG, XSEG określają segmenty absolutne odpowiednio w przestrzeni: danych adresowanych bitowo, kodu, wewnętrznej przestrzeni danych adresowanych bezpośrednio, wewnętrznej przestrzeni danych adresowanych pośrednio, zewnętrznej przestrzeni danych. Użycie jednej z wymienionych dyrektyw powoduje, że program asemblujący kończy wcześniejszy segment, jeśli taki był, w danej klasie pamięci i tworzy nowy segment absolutny w wyspecyfikowanej klasie, 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. BSEG AT 20h ;absolutny segment bitowy od 20h DEC_FLAGA: DBIT 1 ;bit o adresie absolutnym INC_FLAGA: DBIT 1 CSEG AT 100h ;absolutny segment kodu od 100h PARZ_TAB: DB 00h ;parzystość dla 00h DB 01h ;01h DB 00h ;02h DB 01h ;03h DB 01h ;FEh DB 00h ;FFh DSEG AT 40h ;absolutny segment danych od 40h TMP_A: DS 2 ;słowo danych o adresie absolutnym TMP_B: DS 4 TMP_IA: DS 2 TMP_IB: DS 4 ISEG AT 80h ;absolutny segment danych w pamięci ;adresowanej pośrednio od 80h XSEG AT 1000h ;absolutny segment w zewnętrznej ;pamięci danych od 1000h NAZWA1: DS 25 ;dana w pamięci zewnętrznej o adresie NAZWA2: DS 25 ;absolutnym WERSJA: DS 25 BSEG ;dalsza część absolutnego NOWA_FLAGA: DBIT 1 ;segmentu bitowego 2.3 Segment domyślny Na początku procesu asemblacji pliku źródłowego, program asemblujący domyślnie przyjmuje, że wybrany został segment kodu. Dodatkowo licznik położenia przypisany do tego segmentu inicjowany jest adresem 0000H. Umożliwia to stworzenie prostego programu bez konieczności określania segmentów relokowalnych i/lub absolutnych. 3. 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. 3
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 EQU symbol EQU rejestr symbol SET symbol SET rejestr symbol nazwa symboliczna do zdefiniowania. Wyrażenie lub rejestr wyspecyfikowany w dyrektywach EQU lub SET będzie wstawiany przy każdym wystąpieniu symbolu w bieżącym programie asemblerowym. numeryczne, które nie zawiera odniesień w przód lub jest prostym m relokowalnym. 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 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. GRANICA EQU 1200 ROZMIAR EQU GRANICA 200 + 'A' SERIAL EQU SBUF ACCU EQU A LICZNIK1 EQU R5 WARTOSC SET 100 WARTOSC SET WARTOSC / 2 LICZNIK2 SET R1 TEMP SET LICZNIK2 TEMP SET WARTOSC * WARTOSC BIT, CODE, DATA, IDATA, XDATA Dyrektywy BIT, CODE, DATA, IDATA, XDATA przyporządkowują danemu symbolowi adres w określonym typie pamięci. Symbole zdefiniowane za pomocą dyrektyw BIT, CODE, DATA, IDATA, XDATA nie mogą być zmieniane, jak również redefiniowane. Omawiane dyrektywy mają następujący format: symbol BIT adres_bit symbol CODE adres_code symbol DATA adres_data symbol IDATA adres_idata symbol XDATA adres_xdata symbol adres_bit adres_code definiowana nazwa symboliczna. Może być używany w każdym miejscu, gdzie wymagany jest adres w pamięci wyspecyfikowanego typu. 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. jest adresem w pamięci kodu z zakresu 0000H.. FFFFH. 4
adres_data jest adresem rejestru SFR z zakresu adresów 80H.. FFH lub adresem z wewnętrznej pamięci danych z zakresu 0.. 7FH. adres_idata jest adresem w wewnętrznej pamięci danych adresowanej pośrednio z zakresu 00H.. FFH. adres_xdata jest adresem w zewnętrznej pamięci danych z zakresu 0000H.. FFFFH. Przykłady DATA_SEG SEGMENT BIT RSEG DATA_SEG ;segment relokowalny adresowany ;bitowo CTRL: DS 1 ;1 bajtowa zmienna (CTRL) ALARM BIT CTRL.0 ;bit w relokowalnym bajcie SHUT BIT ALARM+1 ;następny bit ENABLE_FLAG BIT 60H ;bezwzględny bit DONE_FLAG BIT 24H.2 ;bezwzględny bit RESTART CODE 00H INTVEC_0 CODE RESTART + 3 INTVEC_1 CODE RESTART + 0BH INTVEC_2 CODE RESTART + 1BH SERBUF DATA SBUF ;redefinicja bufora SBUF RESULT DATA 40H RESULT2 DATA RESULT + 2 BUFFER IDATA 60H BUF_LEN EQU 20H BUF_END IDATA BUFFER + BUF_LEN 1 XSEG1 SEGMENT XDATA RSEG XSEG1 DTIM: DS 6 ;rezerwuje 6 bajtów dla DTIM TIME XDATA DTIM + 0 DATE XDATA DTIM + 3 4. Inicjalizacja pamięci Dyrektywy inicjalizujące pamięć są używane do inicjalizacji pamięci kodu stałymi wartościami o rozmiarze jednego lub dwóch bajtów. Zapisywanie pamięci wspomnianymi stałymi odbywa się od miejsca wskazywanego przez bieżącą wartość licznika położenia w obecnie aktywnym segmencie. DB Dyrektywa DB inicjalizuje pamięć wartościami, z których każda ma rozmiar jednego bajta. Omawiana dyrektywa ma następujący format: etykieta: DB, etykieta jest symbolem, który określa adres inicjowanej pamięci. jest wartością o rozmiarze bajta. Każde może być symbolem, ciągiem znaków lub m. Dyrektywa DB może być umieszczana tylko wewnątrz segmentu kodu programu. Jeśli zostanie użyta w innym segmencie, program asemblujący wygeneruje informację o błędzie. REQUEST: DB 'WCISNIJ DOWOLNY KLAWISZ', 0 TABLE: DB 0,1,8,'A','0', LOW(TABLE),';' ZERO: DB 0, '''' CASE_TAB: DB LOW(REQUEST), LOW(TABLE), LOW(ZERO) KODY_LED DB 23H ;kod zera 5
DB 3FH ;kod jedynki DB 0FAH ;kod dziewiątki DW Dyrektywa DW inicjalizuje pamięć wartościami, z których każda ma rozmiar dwóch bajtów. Omawiana dyrektywa ma identyczny format, jak dyrektywa DB. etykieta: DW, etykieta jest symbolem, który określa adres inicjowanej pamięci. jest wartością o rozmiarze dwóch bajtów. Każde może być symbolem, ciągiem znaków lub m. Dyrektywa DW może być umieszczana tylko wewnątrz segmentu kodu programu. Jeśli zostanie użyta w innym segmencie, program asemblujący wygeneruje informację o błędzie. TABLE: DW 1234, 233AH, QR CASE_TAB: DW CASE0, CASE1, CASE2, CASE3, CASE4 DW $ 5. Rezerwacja pamięci Dyrektywy rezerwacji pamięci są używane do rezerwacji przestrzeni jednostkami o rozmiarze: bajta, słowa lub bitu. Rezerwacja 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. Jej format jest następujący: etykieta DBIT etykieta jest symbolem, który określa adres w 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 wszędzie tam, gdzie dopuszczalne jest użycie segmentu tego typu. liczba rezerwowanych jednostek, każda o rozmiarze jednego bita Wyrażenie nie może zawierać odniesień w przód, symboli relokowalnych lub symboli zewnętrznych. Dyrektywa DBIT rezerwuje przestrzeń w segmencie adresowanym bitowo rozpoczynając od bieżącego adresu. Licznik położenia związany z segmentem bitowym jest zwiększana o wartość. Należy pamiętać, że licznik położenia dla segmentu bitowego odnosi się do bitów nie do bajtów. ON_FLAG: DBIT 1 ; rezerwuje fragment pamięci o rozmiarze 1 bita OFF_FLAG: DBIT 2 ; rezerwuje fragment pamięci o rozmiarze 2 bitów UWAGA. Asembler firmy Keil jest asemblerem dwuprzebiegowym. W pierwszym przejściu, zbierane są wszystkie symbole oraz określana jest długość każdej instrukcji. W drugim przejściu, obliczane są wyrażenia z doniesieniami w tył oraz tworzony jest kod obiektów. Z tego powodu wyrażenia używane w dyrektywie DBIT nie mogą zawierać odniesień w tył. 6
DS Dyrektywa DS rezerwuje określoną liczbę bajtów w przestrzeni pamięci danych. Jej format ma następującą postać: etykieta: DS etykieta jest symbolem, 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. jest liczbą rezerwowanych jednostek, każda o rozmiarze jednego bajta. 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. Jest on następnie zwiększany o wartość. Suma licznika położenia i wartości nie może przekroczyć granicznego rozmiaru dostępnej przestrzeni adresowej w danym segmencie. GAP: DS (($ + 12) AND 0FFF0H) $ DS 20 TIME: DS 8 Uwaga zawarta w opisie dyrektywy DBIT dotyczy również dyrektywy DS. 6. Kontrolowanie adresów w segmentach Poniższe dyrektywy umożliwiają sterowanie wartością licznika położenia lub symbolami rejestrów absolutnych. Dyrektywa jest używana do zmiany wartości licznika położenia w obecnie aktywnym segmencie i ustalenia nowego adresu od którego będą umieszczane dalsze instrukcje. Omawiana dyrektywa ma następujący format: musi być m 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 program asemblujący napotka dyrektywę, obliczana jest wartość i zmieniana wartość licznika położenia dla bieżącego segmentu. Jeśli instrukcja wystąpi w segmencie absolutnym, to do licznika położenia jest zapisywana wartość adresu absolutnego. Jeśli instrukcja wystąpi w segmencie relokowalnym, to do licznika położenia zapisywana jest wartość określająca offset wyspecyfikowanego wyrażenia. Dyrektywa zmienia licznik położenia, nie tworząc przy tym nowego segmentu. Użycie tej dyrektywy może powodować powstawanie dziur w segmencie. W segmencie absolutnym licznik położenia może nie odnosić się do wcześniejszego adresu będącego adresem bazowym segmentu. 100H RESTART EXIT1 ($ + 16) AND 0FFF0H 7
USING Dyrektywa USING określa, który bank rejestrów ma być użyty dla kodowania rejestrów AR0 do AR7. Jej format jest określony jak poniżej: USING jest numerem banku rejestrów 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 jest 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. USING 3 PUSH AR2 ;odłóż na stos rejestr 2 z banku 3 USING 1 PUSH AR2 ;odłóż na stos rejestr 2 z banku 1 UWAGA. Kiedy do zdefiniowania symboli dla ARn użyta jest dyrektywa EQU, to 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. 7. Inne dyrektywy NAME Dyrektywa NAME określa nazwę, która będzie użyta dla oznaczenia modułu obiektowego wygenerowanego na podstawie 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 jest nazwą, która będzie użyta do oznaczenia modułu obiektowego. Jej długość nie może przekroczyć 40 znaków. Przy określaniu nazwy modułu należy przestrzegać zasad określonych dla nazw symbolicznych. W danym pliku programu dyrektywa NAME może być użyta tylko jeden raz. Jeśli omawiana dyrektywa nie zostanie w ogóle użyta, to nazwą modułu obiektowego będzie nazwa pliku źródłowego bez rozszerzenia. Przykład: NAME MOJ_MODUL 8
END Dyrektywa END określa koniec modułu asemblerowego. Tekst, który występuje za dyrektywą END jest ignorowany przez program asemblujący. Dyrektywa END jest wymagana w każdym pliku asemblerowym. Przykład: END 8. Symbole Symbol jest nazwą definiowaną 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ń. Symbole mogą składać się z maksymalnie 31 znaków należących do poniższej listy: A-Z, a-z, 0-9, _,? Nazwa symbolu 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 EQU 5 PRAWDA SET 1 FALSZ SET 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, gdyż są łatwiejsze do zrozumienia i zapamiętania, niż adres lub stała numeryczna. 9. 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: DS 2 ETYK_2: ;etykieta na siebie samą LICZBY: DB 27, 33, ZNAKI, 0 ;etykieta na stałe wartości KOPIUJ: MOV R6, #12H ;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 pamięci programu. Przy definiowaniu etykiety automatycznie przypisywana jest jej bieżącą wartość licznika położenia w danym segmencie. 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. 9
10. Wyrażenia i operatory Operand (argument operacji) może być stałą numeryczną, symbolem, ciągiem znakowym lub m. 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ą tylko 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. 10.1 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 zapisie liczby. 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 Przyrostek Dopuszczalne znaki Przykłady Szesnastkowa H, h 0-9, A-F, a-f 1234H 0A0F0H 0F0H 1a24h 34fcH Dziesiętna D, d 0-9 123 23D 2092d Ósemkowa O, o, Q, q 0-7 172q 34Q 345o 44O Dwójkowa B, b 0 i 1 1001011b 10011B Pierwszym znakiem liczby musi być zawsze cyfra z zakresu 0 do 9. Dlatego liczby szesnastkowe, których zapis wartości zaczyna się od litery muszą być poprzedzone cyfrą 0. 10.2 Znaki Program asemblujący dopuszcza 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 jest przeliczane na wartość 0041H AB jest przeliczane na wartość 4142H a jest przeliczane na wartość 0061H ab jest przeliczane na wartość 6162H ciąg pusty jest przeliczany na wartość 0000H abc generuje BŁĄD 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 10.3 Ciągi znaków Ciągi znaków mogą być używane w połączeniu z dyrektywą DB do definiowania wiadomości używanych 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 10
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? 11