Dyrektywy asemblera Dyrektywy w języku asemblera spełniają dwie funkcje: definiują dodatkowe elementy programu (jak stałe, napisy, makra itp.), sterują pracą kompilatora etykieta:.dyrektywa argument ;komentarz BYTE CSEG DB, DW DD, DQ DEF DEVICE DSEG DW ENDMACRO, ENDM EQU ESEG EXIT INCLUDE LIST LISTMAC MACRO NOLIST ORG SET UNDEF rezerwuje zasoby w SRAM początek segmentu kodu wprowadza stałe 1, 2 bajtowe wprowadza stałe 3, 4 bajtowe nadaje rejestrowi inną nazwę określa typ mikrokontrolera początek segmentu danych wprowadza stałe 2 bajtowe koniec definicji makroinstrukcji definiowanie stałych początek segmentu EEPROM koniec kompilacji pliku dołączenie wskazanego pliku tworzenie raportu z kompilacji raport z kompilacji z makro definicja makroinstrukcji wyłączenie raportu z kompilacji początek adresacji segmentu przypisanie wartości wyraŝenia odwołuje nazwę rejestru (DEF)
Definicje DEF Nadaje rejestrowi roboczemu wybraną nazwę, którą następnie moŝna uŝywać w instrukcjach..def nazwa = symbol rejestru.def acc = r16 ;nazwa acc występująca jako argument w instrukcji jest rejestrem r16. UNDEF Odwołuje nadaną wcześniej nową nazwę rejestru..undef acc EQU SłuŜy do definiowania stałych - przydziela ona identyfikatorowi (nazwie) wartość wyraŝenia. Tak zdefiniowana stała moŝe być wykorzystywana, ale nie zmieniana czy teŝ redefiniowana..equ nazwa = wyraŝenie.equ x1 = 'x' ; x1 przyporządkowano wartość bitową, odpowiadającą małej literze x.equ x2 = 145 ; identyfikator x2 ma wartość liczbową 145 SET Przypisuje wartość wyraŝenia identyfikatorowi. Identyfikator moŝe być uŝyty w innym wyraŝeniu oraz redefiniowany w dalszej części programu..set nazwa = wyraŝenie.set io_offset = 0x23.SET porta = io_offset + 2
Segmenty programu CSEG Wszystkie dalsze zapisy (instrukcji, danych włączonych do kodu itp.) dotyczą pamięci programu (pamięć FLASH). Miejsce (w sensie adresowym) umieszczenia generowanego przez kompilator kodu wynika z dyrektywy ORG. Kolejne zapisy powodują automatyczne zwiększanie adresu. JeŜeli w programie nie wystąpi Ŝadna dyrektywa określająca rodzaj segmentu, to kompilator wszystko umieści w segmencie CSEG. W obrębie tego segmentu nie mogą występować dyrektywy przewidziane do deklaracji zmiennych. Brak wystąpienia dyrektywy ORG implikuje adresację od adresu o wartości 0 (zero). Dyrektywa nie zawiera argumentów..cseg.cseg Main: sbi PORTB,0 ;PORTB.0 = 1 DSEG Wszystkie dalsze zapisy definiują zmienne. Adres, pod jakim zostanie umieszczona zmienna moŝe być zmieniany dyrektywą ORG. Brak dyrektywy ORG w obszarze przewidzianym na zmienne oznacza, Ŝe kompilator zacznie adresować je od adresu $60. W obrębie segmentu danych nie moŝna utworzyć zmiennej, która ma określoną wartość początkową..dseg.dseg var:.byte 1 ;zarezerwowanie jednego bajtu pamięci dla zmiennej var. ESEG Wszystkie dalsze zapisy odnoszą się do pamięci EEPROM. W segmencie zapoczątkowanym przez dyrektywę ESEG znajdują się tylko dyrektywy DB, DW, DD i DQ. Adresy zmiennych są określane dyrektywą ORG (brak specyfikacji ORG w obrębie pamięci EEPROM oznacza wartość początkowa równą zero). W tym segmencie moŝliwe jest, oprócz zdefiniowania zmiennej, nadanie jej określonej wartości początkowej. W trakcie programowania mikrokontrolera programator umieszcza w pamięci określone wartości początkowe. W czasie pracy programu wartości tych zmiennych moŝna zmienić. KaŜde następne uruchomienie programu w zmiennych tych będzie zawierać wartość ostatnio zapisaną. (zmienne same nigdy nie utracą swej wartości)..eseg.eseg CodeArr:.DB '0', '1'
ORG Dyrektywa ORG słuŝy do określenia komórki pamięci (adresu), gdzie kompilator rozpocznie umieszczanie słów programu (jeŝeli dyrektywa ORG jest uŝyta w obrębie CSEG) lub określa adres początku bloku zmiennych (jeŝeli dyrektywa jest uŝyta w obrębie DSEG). Dyrektywa ta wymaga uŝycia argumentu w postaci wyraŝenia określającego adres. W obrębie segmentu kodu programu dyrektywa uŝywana jest do "usztywnienia" ściśle określonych miejsc w programie (głównie do wskazania początków obsługi przerwań, na które reakcja jest ściśle określona w adresacji programu)..org wyraŝenie ; wyraŝenie wskazuje adres pamięci.dseg RAM_Variable1:.BYTE 1 RAM_Variable2:.BYTE 1.ORG $800 RAM_Variable3:.BYTE 1 Umieszczenie dyrektywy DSEG (jeŝeli jest pierwsze) oznacza, Ŝe zgłoszone zmienne (RAM_Variable1 i kolejne) będą umieszczane w pamięci SRAM poczynając od adresu $60. UŜycie dyrektywy ORG spowodowało zmianę adresu, pod którym będą umieszczane zmienne na $800. Zmienne w pamięci danych BYTE Rezerwuje zasoby w pamięci SRAM. MoŜe być uŝywana jedynie w segmencie danych (DSEG). BYTE wymaga jednego argumentu określającego wielkość rezerwowanych zasobów dla zmiennej określonej w etykiecie, która musi poprzedzać dyrektywę BYTE. Wielkość definiowanej zmiennej moŝe być zapisana w postaci wyraŝenia arytmetycznego (w wyraŝeniu mogą wystąpić bezpośrednio liczby i identyfikatory wcześniej zdefiniowanych stałych liczbowych), którego wartość jest wyliczalna przez kompilator. etykieta:.byte wyraŝenie.dseg Bufor:.BYTE 16 ; rezerwuje 16 bajtów dla Bufor
Stałe w pamięci programu i EEPROM DB, DW, DD, DQ Rezerwują zasoby w pamięci programu lub pamięci EEPROM. Dyrektywy te muszą być poprzedzone etykietą i wymagają argumentów, które mogą mieć postaci listy wyraŝeń (co najmniej jedno wyraŝenie). Etykieta określa adres inicjowanych zasobów pamięci, wyraŝenie dla DB to wartość bajtowa, a dla DW, DD, DQ dwu-, trzy-, cztero-bajtowa. Dyrektywa DB wprowadza stałe o strukturze bajtowej (liczby stałe bajtowe oraz napisy), dyrektywa DW wprowadza stałe o strukturze dwubajtowej (liczby stałe 16-bitowe, adresy zmiennych i etykiet w programie). W przypadku uŝycia dyrektywy DB naleŝy pamiętać, Ŝe obszar wprowadzany tą dyrektywą zostanie uzupełniony bajtem o wartości zero gdy jego wielkość będzie nieparzysta. W dyrektywach tych pod symbolem lista wyraŝeń naleŝy rozumieć listę wyraŝeń rozdzielonych przecinkami. Długie listy stałych w dyrektywach moŝna przenosić do następnego wiersza (pamiętając o tym, by przerwać listę po parzystej liczbie bajtów) poprzez ponowne uŝycie tej samej dyrektywy ale bez etykiety. W przypadku uŝycia dyrektywy DW, w pierwszej kolejności zapisany jest bajt będący młodszą częścią stałej oraz następnie bajt będący starszą częścią stałej. etykieta:.db lista wyraŝeń etykieta:.dw lista wyraŝeń Przykłady: Function:.DB 0x0D,0x0A,"System kontroli.",0x0d,0x0a ;nowy wiersz.db "Wersja sprzętu: 1.00",0x0D,0x0A CodeArr:.DB '0', '1'.DB '2', '3' ;we wszystkich przypadkach lista stałych zawiera parzystą liczbę bajtów, Makroinstrukcje MACRO Oznacza początek definicji makroinstrukcji. Dyrektywa wymaga argumentu będącego nazwą makroinstrukcji. Makroinstrukcje mogą zawierać maksymalnie 10 parametrów oznaczanych @0 - @9. W programie wywołanie makroinstrukcji polega na umieszczeniu jego nazwy oraz parametrów oddzielonych przecinkami. ENDMACRO, ENDM Koniec definicji makroinstrukcji zapoczątkowanej dyrektywą MACRO..MACRO nazwa makroinstrukcji.endmacro lub.endm.macro ldz ldi r30, low(@0) ldi r31, high(@0).endmacro ; początek definicji makroinstrukcji ; koniec definicji makroinstrukcji
Dyrektywy sterujące kompilacją DEVICE SłuŜy do poinformowania kompilatora dla jakiego modelu mikrokontrolera ma być generowany kod programu. W kaŝdym programie musi wystąpić jeden raz. Zwykle w programie dyrektywą INCLUDE dołącza się do programu jeden z plików definiujących środowisko mikrokontrolera i tam między innymi zawarta jest ta dyrektywa..device symbol mikrokontrolera.device ATmega16 INCLUDE Włącza do kompilacji wskazany plik. Kompilacja trwa do końca pliku lub do napotkania dyrektywy EXIT. Nazwa dołączanego pliku powinna być umieszczona między znakami " "..INCLUDE "nazwa pliku ".INCLUDE "m16def.inc" ; dołączenie pliku definiującego mikrokontroler ATmega16 LIST Informuje kompilator o konieczności stworzenia raportu z kompilacji..list.nolist.include "m16def.inc".list ; wyłączenie raportu z kompilacji ; dołączenie pliku ; ponowne załączenie raportu z kompilacji NOLIST Dyrektywa NOLIST informuje kompilator o konieczności wyłączenia raportu z kompilacji..nolist.nolist.include " m16def.inc " ; wyłączenie z raportu z kompilacji dołączonego pliku m16def.inc
LISTMAC Informuje kompilator o konieczności dołączenia do raportu z kompilacji informacji z kompilacji makroinstrukcji..listmac.nolist.include " m16def.inc ".LIST.LISTMAC ; wyłączenie raportu z kompilacji ; dołączenie pliku ; ponowne załączenie raportu ; dołączenie informacji o makroinstrukcji EXIT Zakończenie kompilacji z danego pliku. Podczas normalnej pracy kompilacja trwa do końca pliku jeŝeli jednak w dołączonym przez dyrektywę INCLUDE pliku pojawi się dyrektywa EXIT to kompilator zakończy kompilację dołączonego pliku i będzie kontynuował pracę od linii następnej po dyrektywie INCLUDE..EXIT.EXIT ; koniec kompilacji
Struktura programu RESET Przerwania Inicjalizacja Program główny END.dseg dane:.byte 1.cseg rst: jmp start ;tablica wektorów przerwań ;procedury obsługi przerwań start: ;inicjalizacja ;konfiguracja I/O petla: ;program główny : : jmp petla ;procedury pomocnicze ;pliki dołączane do pliku gł. Po włączeniu napięcia zasilania w programie uŝytkownika odbywa się jednorazowa inicjalizacja, np. ustalenie trybu pracy urządzeń peryferyjnych. Właściwy program uŝytkownika jest realizowany częściowo w niekończącej się pętli głównej, a częściowo w obsługach przerwań.
Proces tworzenia programu w języku asemblera
Przykładowy program ;-------------------------- Zapalanie i gaszenie diody LED-------------------------.nolist.include "m16def.inc".list.listmac ;-------------------- Początek segmentu kodu (Code Segment) ------------------.cseg ;.org 0 ; rjmp ResetProcessor ; ;----------------- Tabela wektorów przerwań (Interrupt Vectors) ----------------.org INT0addr ; External Interrupt0 Vector reti ; Address.org INT1addr ; External Interrupt1 Vector reti ; Address.org ICP1addr ; Input Capture1 Interrupt reti ; Vector Address.org OC1addr ; Output Compare1A reti ; Interrupt Vector Address.org OVF1addr ; Overflow1 Interrupt Vector reti ; Address.org OVF0addr ; Overflow0 Interrupt Vector reti ; Address.org URXCaddr ; UART Receive Complete reti ; Interrupt Vector Address.org UDREaddr ; UART Data Register Empty reti ; Interrupt Vector Address.org UTXCaddr ; UART Transmit Complete reti ; Interrupt Vector Address.org ACIaddr ; Analog Comparator reti ; Interrupt Vector Address ;--------------------------------------------------------------------------------------------- ResetProcessor : ; cli ; zablokowanie przerwań ldi r16, LOW(RAMEND) ; inicjacja stosu out SPL, r16 ; programowego ldi r16,$ff out DDRB,r16 out PORTB,r16 ldi r16, $FC out DDRD, r16 ; cały port B jako wyjściowy ; wszystkie wyjścia portu B ; w stanie wysokim ; PD0 i PD1 jako wejścia, ; reszta jako wyjścia ldi r16, $FF ; wszystkie wyprowadzenia out PORTD, r16 ; portu D w stanie wysokim ;---------------------------------------------------------------------------------------------
Main_0 : ; początek pętli głównej in r16,pind ; wczytanie PIND do r16 andi r16,0x03 ; iloczyn logiczny r16 i 3 cpi r16,0x02 ; czy jest przyciśnięty SW1 breq Main_1 ; tak - to skocz do Main_1 cpi r16,0x01 ; czy jest przyciśnięty SW4 breq Main_2 ; tak - to skocz do Main_2 rjmp Main_0 ; powrót do pętli głównej ;--------------------------------------------------------------------------------------------- Main_1 : ; cbi PORTB,0 ; PB0 = 0 - dioda świeci rjmp Main_0 ; powrót do pętli głównej ;--------------------------------------------------------------------------------------------- Main_2 : ; sbi PORTB,0 ; PB0 = 1 - dioda nie świeci rjmp Main_0 ; powrót do pętli głównej ;---------------------------------------------------------------------------------------------.exit ; koniec kompilacji ;---------------------------------------------------------------------------------------------