MCS-51
Wprowadzenie do asemblera

Etykiety

Pomimo zaprezentowanych do tej pory udogodnień, istotnym problemem utrudniającym pisanie programów pozostaje adresowanie rozkazów skoku, które zostaną omówione w dalszej części tego opracowania. W przykładowym programie

MOV  A,#10
MOV  SBUF,A
INC  A
LJMP 0002h

END

wykorzystującym instrukcję skoku bezwarunkowego LJMP, skok jest wykonywany do miejsca położonego o dwie instrukcje wcześniej (w prezentowanym przykładzie zakłada się, że program jest umieszczany w pamięci kodu od adresu 0000h). Gdyby jednak należało skoczyć w przód, do instrukcji położonej dalej, to obliczenie wartości argumentu w chwili umieszczania rozkazu skoku w kodzie programu, bez dokładnej znajomości dalszych instrukcji, mogłoby być niemożliwe. Skomplikowane jest też obliczenie argumentu rozkazu skoku adresowanego względnie (np. SJMP). Co gorsza, każda modyfikacja programu zmieniająca jego długość może wymagać zmiany w adresacji właśnie w instrukcjach skoków.

Aby uniknąć tego typu kłopotów wprowadzono symboliczne oznaczanie adresów w programie. Instrukcję, do której ma być wykonany skok, wyróżnia się nazwą symboliczną określaną mianem etykiety (ang. label). Następnie nazwę tę umieszczamy w miejscu argumentu rozkazu skoku. Przykładowy program przyjmie teraz następującą postać.

       MOV  A,#10
BACK:  MOV  SBUF,A
       INC  A
       LJMP BACK
       
       END

BACK jest tutaj etykietą oznaczającą adres instrukcji, do której ma nastąpić skok za pomocą instrukcji LJMP.

Jak widać z zaprezentowanego przykładu etykieta jest nazwą symboliczną zakończoną znakiem dwukropka. Zatem wszystkie zasady dotyczące tworzenia tych nazw mają zastosowanie przy tworzeniu etykiet. Podczas ich definiowania, etykieta musi być pierwszym polem tekstowym w linii. Dopuszcza się jedynie poprzedzanie jej znakami tabulacji i/lub spacji. Znak dwukropka musi wystąpić bezpośrednio po nazwie symbolicznej etykiety. W linii kodu może być zdefiniowana tylko jedna etykieta. Na przykład:

ETYK_1:   DS   2                 ;etykieta na komórkę w wewnętrznej..
                                 ;..pamięci danych
ETYK_2:                          ;etykieta na siebie samą
LICZBY:   DB   27,33,'ZNAKI',0   ;etykieta na stałe w pamięci kodu
KOPIUJ:   MOV R6,#12H            ;etykieta na instrukcję w programie

W powyższym przykładzie, ETYK_1, ETYK_2, LICZBY i KOPIUJ są etykietami.

Etykiety w połączeniu z niektórymi dyrektywami mogą również służyć do symbolicznego oznaczania adresów nie tylko w pamięci kodu, lecz również w pamięci danych, co przedstawiono w pierwszej linii powyższego przykładu. Zatem w ogólności etykieta może reprezentować nie tylko adres w pamięci kodu, lecz także w innych przestrzeniach pamięci, gdyż podczas jej definicji automatycznie przypisywana jest jej bieżącą wartość licznika położenia bieżącego segmentu.

W programie asemblerowym etykiety wykorzystywane są także przy wywoływaniu podprogramów (wywołanie podprogramu np. za pomocą instrukcji LCALL jest również swego rodzaju skokiem), służąc do oznaczenia jego pierwszej instrukcji. W takim przypadku wykonywany jest kod znajdujący się za etykieta, aż do napotkania instrukcji RET.

Uwaga Czasami zastosowana etykieta jest dość długa, spychając instrukcję na którą wskazuje, zbyt daleko w prawo, co utrudnia późniejszą analizę całego kodu, gdyż wpływa na jego wizualny wygląd. Warto więc pamiętać, że etykieta wskazuje na rozkaz umieszczony w tej samej linii lub następnej niepustej zawierającej instrukcję. Dlatego przedstawione poniżej przykłady są sobie równoważne.
       MOV  A,#10                              MOV  A,#10
MIEJSCE_SKOKU:  MOV  SBUF,A             MIEJSCE_SKOKU:
       INC  A                                  MOV  SBUF,A
       LJMP MIEJSCE_SKOKU                      INC  A
                                               LJMP MIEJSCE_SKOKU
       END                                     END

Etykieta składająca się z danej nazwy symbolicznej może być zastosowana tylko raz w danym pliku źródłowym. Wynika to z faktu, iż przy wykorzystaniu takiej etykiety np. w instrukcji skoku bezwarunkowego program asemblujący nie byłby w stanie jednoznacznie określić adresu komórki pamięci kodu, do której ma nastąpić skok. Taka sytuacja ma miejsce w poniższym przykładzie.

       ...
MIEJSCE_SKOKU:
       ...
       SJMP MIEJSCE_SKOKU
       ...
MIEJSCE_SKOKU:
       ...