Lista instrukcji procesora 8051 część 2 Skoki i wywołania podprogramów, operacje na stosie, operacje bitowe Ryszard J. Barczyński, 2009 2013 Politechnika Gdańska, Wydział FTiMS, Katedra Fizyki Ciała Stałego Materiały dydaktyczne do użytku wewnętrznego
Przeniesienie sterowania Nasze dotychczasowe instrukcje wykonują się sekwencyjnie jedna po drugiej Programy, które rozwiązyją rzeczywiste problemy muszą mieć oczywiście możliwość zmiany sekwencji wykonywanych instrukcji w zależności od pewnych warunków If akumulator jest równy 0 then Odpal rakietę Else Poczekaj jeszcze chwilkę Osiąga się to przez instrukcje skoków i skoków warunkowych (czyli przez przeniesienie sterowania oraz warunkowe przeniesienie sterowania)
Przeniesienie sterowania Mamy do wykonania następujące zadanie: Wylicz R1 + R0 i zachowaj w A Umieść 0 w R2 If A = 0 then Umieść 13 w R2 Wylicz R2 + R3 i umieść wynik w R5 By wykonać to zadanie potrzebujemy instrukcji skoku warunkowego JZ rel A = R1+R0 R2 = 0 A == 0 TRUE R2 = 13 R5 = R2 + R3 FALSE
Przeniesienie sterowania: JZ rel Instrukcja JZ rel Jeżeli A jest równe zero zmienia licznik programu (czyli adres następnej instrukcji) o wartość równą rel rel jest 8 bitową liczbą ze znakiem możliwe jest przeniesienie sterowania zarówno w przód, jak i w tył Instrukcja ma długość 2 bajtów By zrozumieć jak działa ta instrukcja (i inne instrukcje skoków) przyjrzyjmy się jeszcze adresowaniu instrukcji w pamięci programu.
Adresowanie instrukcji Rozważmy sekwencję poniższych instrukcji MOV A,R0 ADD A,#55 MOV R5,A MOV R1,#26H Niektóre z instrukcji maja rozmiar jednego bajtu, niektóre dwóch. W pamięci programu kod będzie miał następującą postać: E8 24 37 FD 79 26 } } } } MOV A,R0 ADD A,#55 MOV R5,A MOV R1,#26H
Adresowanie instrukcji Sekwencja działań procesora podczes wykonywania programu jest następująca PC zawiera adres instrukcji, która ma być wykonana Następuje pobranie instrukcji i jej dekodowanie Opcode Operandy PC jest zwiększany o rozmiar instrukcji Ustalony w oparciu o opcode Instrukcja jest wykonywana Instrukcje skoku po prostu modyfikują rejestr PC
Przeniesienie sterowania: JZ rel Rozważmy instrukcję JZ rel w poniższym przykładzie MOV A,R0 ADD A,#55 JZ 1 MOV R5,A MOV R1,#26H 0000H 0001H 0002H 0003H 0004H 0005H 0006H 0007H E8 24 37 60 01 FD 79 26 } } } } MOV A,R0 ADD A,#55 } JZ 01 MOV R5,A MOV R1,#26H Po wykonaniu instrukcji JZ gdy A jest równy zero rejestr PC będzie zawierał 0006H, a w przeciwnym wypadku 0005H
Przeniesienie sterowania: JZ rel W ogólności licznik programu (PC) zostanie zmodyfikowany następująco If A is zero then PC = PC + rel Już przed wykonaniem instrukcji PC został zwiększony o 2 To jest rozmiar instrukcji JZ rel Gdy A jest różne od zera, wtedy rel nie jest dodawany do PC i zawiera on adres instrukcji następnej po JZ Wartość rel może być pomiędzy 128 i +127 Skoki mogą być zatem wykonane w przód i w tył.
Przeniesienia sterowania: Dobra wiadomość: zwykle nie musimy liczyć adresów... Assembler zrobi to za nas! Zamiast MOV A,R0 ADD A,#55 JZ 1 MOV R5,A MOV R1,#26H JZ rel Używamy etykiet Symbolicznych nazw adresów Assembler wyliczy przesunięcie MOV A,R0 ADD A,#55 JZ fin MOV R5,A fin: MOV R1,#26H Uwaga: Większość assemblerów interpretuje operand JZ jako adres, a nie adres względny!!!
Przeniesienie sterowania: JNZ rel Instrukcja JNZ rel Jest podobna do JZ rel, ale skok jest wykonywany wtedy, gdy zawartość akumulatora jest różna od zera
A = R1+R0 Przykład: JNZ rel R2 = 0 A == 0 R2 = 13 TRUE FALSE next: MOV A,R0 ADD A,R1 MOV R2,#0 JNZ next MOV R2,#13 MOV A,R2 ADD A,R3 R5 = R2 + R3
Przeniesienie sterowania: JC rel Instrukcja JC rel Skok jest wykonywany wtedy, gdy zawartość flagi przeniesienia C jest równa 1.
Przeniesienie sterowania: JNC rel Instrukcja JNC rel Skok jest wykonywany wtedy, gdy zawartość flagi przeniesienia C jest równa 0.
Przeniesienie sterowania: JB bit,rel Instrukcja JB bit,rel Skok jest wykonywany wtedy, gdy bezpośrednio adresowany bit bit jest równy 1.
Przeniesienie sterowania: JNB bit,rel Instrukcja JNB bit,rel Skok jest wykonywany wtedy, gdy bezpośrednio adresowany bit bit jest równy 0.
Instrukcja Przeniesienie sterowania: JBC bit, rel JBC bit,rel Skok jest wykonywany wtedy, gdy bezpośrednio adresowany bit bit jest równy 1. Bit jest następnie ustawiany na 0. (niezależnie czy skok jest wykonywany)
Przykład Sum = 0 Count = 10 Policzyć sumę liczb od 1 do 10 Rozwiązanie Rysunek pokazuje pętlę Użyjemy rejestrów 8051 R2 do obliczenia sumy R1 jako licznik Sum = Sum + Count Reduce Count by 1 Is Count equal to 0 TRUE FALSE
Przykład R2=0 R1 = 10 MOV R2,#0 MOV R1,#10 R2 = R2 + R1 loop :MOV A,R2 ADD A,R1 MOV R2,A Reduce R1 by 1 MOV A,R1 CLR C SUBB A,#1 MOV A,R1 R1 == 0 FALSE JNZ loop FALSE TRUE TRUE
Przykład (z DEC) Loop: MOV R2,#0 MOV R1,#10 MOV A,R2 ADD A,R1 MOV R2,A MOV A,R1 CLR C SUBB A,#1 MOV R1,A JNZ Loop Loop: MOV R2,#0 MOV R1,#10 MOV A,R2 ADD A,R1 MOV R2,A DEC R1 MOV A,R1 JNZ Loop
Przeniesienie sterowania: CJNE A,#data,rel Nazwa instrukcji: Compare & Jump if Not Equal (CJNE) Elastyczniejsza niż JZ i JNZ, ale 3 ma bajty długości Działanie: Porównanie zawartości A ze stałą #data i gdy te wielkości nie są równe rel jest dodawane do licznika programu (PC). Modyfikuje flagę C gdy (A) < #data.
Możliwości: Instrukcja CJNE CJNE A,#data,rel CJNE A,direct,rel CJNE Rn,#data,rel Której użyć? Zależy co porównujesz... CJNE @Ri,#data,rel Wszystkie powyższe instrukcje porównują dwie wielkości i wykonują skok, gdy nie są one równe (oraz ustawiają odpowiednio wskaźnik C) > rejestr A ze stałą > rejestr A z zawartością komórki pamięci > rejestr Rn ze stałą > zawartość komórki pamięci adresowanej pośrednio ze stałą
Przykład: CJNE W zależności od R4 wykonaj różne fragmenty kodu Test: Less: Greater: Endtest: CJNE R4,#0H,Less ; R4 równy zero JMP Endtest MOV A,R4 ANL A,#80H CJNE A,#80H,Greater ; Mniej ni ż zero JMP Endtest ; Większy od zera
Przeniesienie sterowania: DJNZ Rn,rel Następna uniwersalna i złożona instrukcja skoku: Decrement & Jump if Not Zero (DJNZ) Używana do wykonywania pętli z licznikiem Zawartość rejestru Rn jest zmniejszana o 1, a następnie jezeli wynik jest różny od zera licznik programu (PC) jest modyfikowany zostaje do niego dodana wartość rel (czyli zostaje wykonany skok).
Instrukcja DJNZ Możliwe formaty DJNZ Rn,rel DJNZ direct,rel Wskaźniki nie są modyfikowane Obie instrukcje zmniejszają zawartość pierwszego operandu i wykonują skok jeżeli się wyzerował. > Pierwsza instrukcja dekrementuje i testuje Rn» rozmiar 2 bajtów > Druga instrukcja (mocna!) dekrementuje i testuje bezpośrednio adresowaną komórkę pamięci» rozmiar 3 bajtów
Przykład (z DJNZ) Loop: MOV R2,#0 MOV R1,#10 MOV A,R2 ADD A,R1 MOV R2,A MOV A,R1 CLR C SUBB A,#1 MOV R1,A JNZ Loop Loop: CLR A MOV R1,#10 ADD A,R1 DJNZ R1,Loop MOV R2,A
Instrukcje skoków Potrzebujemy również instrukcji skoków bezwarunkowych Ładują one adres do rejestru PC Odpowiadają instrukcji goto języków wyższego poziomu Nie ma ograniczeń odnośnie adresu docelowego Ostrożnie... Używane w wielu wypadkach, na przykład Często twotzą główną pętlę programu W konstrukcji If Else W instrukcji wyboru Wyskoki z pętli
Instrukcje skoków Istnieją 3 instrukcje skoków SJMP rel AJMP addr11 LJMP addr16 Pierwsza to krótki skok względny (SJMP) Do PC jest dodawana 8 bitowa wartość ze znakiem (rel). skacze do 128 bajtów w tył i 127 bajtów w przód ma rozmiar 2 bajtów Przykład: JZ elseif ADD A,R1 MOV R2,#0 SJMP endif elseif: MOV R2,#13 endif: MOV A,R2 ADD A,R3
Instrukcje skoku Druga instrukcja skoku to skok absolutny (AJMP) z użyciem adresu 11 bitowego Niższe 11 bitów PC jest zamieniane przez 11 bitów określonych w instrukcji Rozmiar również 2 bajty Potencjalnie możliwy jest skok dalszy (2047 bajtów) niż za pomocą SJMP. Dokładniej dostępne są wszystkie adresy, które leżą wewnątrz 2K bloku, aktualnie adresowanego przez PC PC a a a a a a a a a a a PC bits unchanged by instruction PC bits modified by instruction
Instrukcje skoku Trzecia instrukcja skoku to długi skok absolutny (LJMP) z użyciem 16 bitowego adresu. 16 bitów rejestru PC jest zamieniane przez 16 bitów adresu wyspecyfikowanych w instrukcji. Skok może być wykonany do dowolnej pozycji w 64K pamięci programu. Rozmiar instrukcji to 3 bajty PC a a a a a a a a a a a a a a a a All PC bits modified by instruction
Instrukcje skoku OK, są 3 instrukcje skoku. Której użyć??? Odpowiedź: Pozwól zadecydować assemblerowi... Użyj instrukcji JMP Assembler wybierze tą właściwą... i zamieni JMP na jedną z 3 instrukcji. Przykład: JZ elseif ADD A,R1 MOV R2,#0 JMP endif elseif: MOV R2,#13 endif: MOV A,R2 ADD A,R3
e_count = 0 o_count = 0 s = start address of string Przykład TRUE is value at s not equal to 0 TRUE is value at s equal to 'e' FALSE FALSE Policz wystąpienia liter 'e' i 'o' w łańcuchu Increment e_count TRUE is value at s equal to 'o' FALSE umieszczonym od adresu 20h i Increment o_count zakończonym 00h. Wyniki umieść w Increment s R1 oraz R2
Przykład: rozwiązanie e_count = 0 o_count = 0 Increment e_count TRUE s = start address of string is value at s not equal to 0 TRUE is value at s equal to 'e' Increment s FALSE FALSE TRUE Increment o_count is value at s equal to 'o' Pisanie w assemblerze raczej nie jest trywialne! FALSE Loop: Testo: Fintest: Loopend: MOV R1,#0 MOV R2,#0 MOV R0,#20H MOV A,@R0 JZ Loopend CJNE @R0,# e,testo INC R1 JMP Fintest CJNE @R0,# o,fintest INC R2 INC R0 JMP Loop
Skok pośredni Specjalna wersja instrukcji skoku JMP @A+DPTR z użyciem 16 bitowego adresu, będącego sumą zawartości DPTR i akumulatora. umożliwia skoki wyliczane według tabeli skoków.
Wywołanie podprogramów Istnieją 2 instrukcje wywołania podprogramów ACALL addr11 LCALL addr16 Powrót z podprogramu (procedury, funkcji) następuje po wykonaniu instrukcji RET Przykład: proc: ADD A,R1 ACALL proc MOV R2,#0... MOV R2,#13 MOV A,R2 RET
Wywołanie podprogramu Pierwsza (ACALL) instrukcja to wywołanie podprogramu z użyciem adresu 11 bitowego (PC) < (PC) + 2 (SP) < (SP) + 1 ((SP)) < (PC7..0) (SP) < (SP) + 1 ((SP)) < (PC15..8) (PC10..0) < addr11 Rozmiar 2 bajty Położenie startu podprogramu w bloku 2047 bajtów. PC czyli adres powrotu (adres następnej instrukcji do wykonania po zakończeniu podprogramu) jest zachowywany na stosie. Inne rejestry nie są zachowywane.
Wywołanie podprogramu Druga (LCALL) instrukcja to wywołanie podprogramu z użyciem adresu 16 bitowego (PC) < (PC) + 2 (SP) < (SP) + 1 ((SP)) < (PC7..0) (SP) < (SP) + 1 ((SP)) < (PC15..8) (PC15..0) < addr16 Rozmiar 3 bajty Położenie startu podprogramu w bloku 2047 bajtów. PC czyli adres powrotu (adres następnej instrukcji do wykonania po zakończeniu podprogramu) jest zachowywany na stosie. Inne rejestry nie są zachowywane.
Wywołanie podprogramu OK, są 2 instrukcje wywołania podprogramu. Której użyć??? Odpowiedź: Pozwól zadecydować assemblerowi... Użyj instrukcji CALL Assembler wybierze tą właściwą... i zamieni CALL na jedną z 2 instrukcji. Przykład: proc: MOV A,#10 CALL proc MOV R2,#0... MOV R2,#13 ADD A,R2 RET
Powrót z podprogramu Instrukcja powrotu (RET) ładuje do licznika programu (PC) adres powrotu zachowany na stosie (PC15..8) < ((SP)) (SP) < (SP) 1 (PC7..0) < ((SP)) (SP) < (SP) 1 Instrukcja znajduje zastosowanie do powrotów z podprogramów wywołanych zarówno długą, jak i któtką instrukcją CALL.
Operacje na stosie: PUSH Umieść na stosie zawartość komórki pamięci PUSH direct do rejestrów SFR można się odwoływać poprzez ich adresy w obszarze SFR (na przykład ACC) adresowanie przez SP jest pośrednie dotyczy do 256 bajtów wewnętrznej pamięci RAM (SP) < (SP) + 1 ((SP)) < direct
Operacje na stosie: POP Pobierz ze stosu zawartość komórki pamięci POP direct do rejestrów SFR można się odwoływać poprzez ich adresy w obszarze SFR (na przykład ACC) adresowanie przez SP jest pośrednie dotyczy do 256 bajtów wewnętrznej pamięci RAM (direct) < ((SP)) (SP) < (SP) 1
Operacje na bitach Procesor 8051 posiada kilka instrukcji umożliwiających manipulację pojedynczymi bitami Rolę akumulatora 1 bitowego pełni wskaźnik C w rejestrze PSW Inne poza nim wskaźniki nie są zmieniane przez te instrukcje, chyba że instrukcja ich explicite dotyczy
Operacje na bitach: CLR Instrukcje zerowania CLR C CLR bit Instrukcja zeruje flagę C lub bezpośrednio adresowany bit w obszarze pamięci RAM adresowalnym bitowo.
Operacje na bitach: SETB Instrukcje ustawiania jedynki SETB C SETB bit Instrukcja ustawia jedynkę na wskaźniku C lub bezpośrednio adresowany bit w obszarze pamięci RAM adresowalnym bitowo.
Operacje na bitach: CPL Logiczna negacja CPL C CPL bit Instrukcja neguje wskaźnik C lub bezpośrednio adresowany bit w obszarze pamięci RAM adresowalnym bitowo.
Operacje na bitach: ANL Logiczny iloczyn ANL C,bit ANL C,/bit Instrukcja liczy logiczny iloczyn C i bezpośrednio adresowanego bitu lub logiczny iloczyn C i negacji bezpośrednio adresowanego bitu wynik jest umieszczany w C.
Operacje na bitach: ORL Logiczna suma ORL C,bit ORL C,/bit Instrukcja liczy logiczną sumę C i bezpośrednio adresowanego bitu lub logiczną sumę C i negacji bezpośrednio adresowanego bitu wynik jest umieszczany w C.
Nie rób nic: NOP Instrukcja NOP Nie wykonuje żadnych czynności oprócz zajmowania pamięci programu i zangażowania czasu procesora.