Programowanie w asemblerze ARM: instrukcje 17 stycznia 2017
Instrukcje sterujace: skoki Instrukcja skoku B etykieta Dzięki sufiksom warunków mamy skoki warunkowe. Adres względny (do pc), w zakresie ok. 32 MB. Wariant BX rejestr pozwala na przejście do trybu Thumb (jeśli dolny bit adresu ustawiony), a także na dynamiczne obliczenie adresu.
Skoki warunkowe Rejestr stanu cpsr (Current Program Status Register) zawiera cztery podstawowe flagi dla warunków: N (Negative), Z (Zero), C (carry) and V (overflow). Skoki warunkowe maja mnemoniki b<warunek>, przy czym warunek to jeden z ciagów liter: eq (equal), neq (not equal), ge (greater or equal, dla liczb ze znakiem), lt (lower than), gt (greather than), le (lower or equal), mi (minus/negative), pl (plus/positive), os (overflow set), oc (overflow clear), hi (higher, bez znaku), ls (lower or same), cs/hs (carry set/higher or same), cc/lo (carry clear/lower).
Wywołania procedur Instrukcja wywołania procedury to skok ze śladem (adresem powrotnym) w rejestrze lr BL etykieta Tu też wolno używać sufiksów warunków. Tak jak B ma wariant BLX rejestr pozwalajacy na przejście do trybu Thumb oraz dynamiczne obliczenie adresu. Ma też wariant BLX etykieta z bezwarunkowym przejściem do trybu Thumb.
Przesłania do/z pamięci Instrukcje LDR rejestr,adres STR rejestr,adres służa do przepisywania 4 bajtów z pamięci do rejestru i odwrotnie. Argument adres składa się z rejestru i przesunięcia, zostanie opisany za chwilę. Warianty do przesyłania pojedynczych bajtów z rozszerzeniem bitu znaku (LDRSB) i bez (LDRB, STRB). Warianty do przesyłania par bajtów z rozszerzeniem bitu znaku (LDRSH) i bez (LDRH, STRHB).
Tryby adresowe Adres składa się zawsze z rejestru adresu bazowego i przesunięcia: rejestru lub stałej. Przy zapisywaniu instrukcji można pominać przesunięcie, oznacza to przesunięcie 0, tzn. poniższe instrukcje sa równoważne LDR r0,[r1] LDR r0,[r1,#0] Indeksowanie z przesunięciem pozwala na pre- i postinkrementację, nazywane nie wiadomo czemu preindex i postindex.
Preinkrementacja Adres efektywny wyznacza się dodajac przesunięcie do bazy. W wariancie podstawowym po wykonaniu przesłania rejestr bazowy nie ulega zmianie LDR r0,[r1,#4] LDR r3,[r4,r5] LDR r5,[r6,r7,lsr #4] W wariancie preindexing with writeback adres efektywny jest wpisywany do rejestru bazowego, co oznacza zwiększenie rejestru bazowego o wartość przesunięcia LDR r0,[r1,#4]!
Postinkrementacja Przy tej metodzie adresem efektywnym jest zawartość rejestru bazowego, natomiast po dokonaniu przesłania jest on zawsze zwiększany o wartość przesunięcia LDR r0,[r1],#4 LDR r5,[r6],-r7,lsr #4
Przesłania wielokrotne Można jedna instrukcja przesłać do/z kilku rejestrów cały blok pamięci LDMIA r0,{r1-r3,r5} STMDB r0,{r1-r3,r5} Ma ona wariant z finalna modyfikacja rejestru bazowego LDMIB r7!,{r1-r3,r5}
Przesłania wielokrotne Bazowy mnemonik operacji to LDM i STM. Modyfikatory określaja, kiedy i jak ma być obliczany adres efektywny IA = Increment After IB = Increment Before DA = Decrement After DB = Decrement Before
Przesłania wielokrotne Przykład: kopiowanie 32 bajtów, adres źródłowy w r0, docelowy w r1 LDMIA r0,{r2-r9} STMIA r1,{r2-r9} Uwaga: kolejność kopiowania jest zgodna z numerami rejestrów, niezależnie od kolejności zapisu w instrukcji.
Operacje na stosie Architektura dopuszcza cztery rodzaje stosów, określone kombinacja dwóch cech: kierunku w jakim przyrasta stos, stos może być rosnacy (A od ascending), gdzie stos przyrasta w kierunku większych adresów malejacy (D od descending) na co wskazuje rejestr wierzchołka sp, stos może być pełny (F od full), sp wskazuje na ostatni zajęty (zapełniony) element stosu pusty (E od empty), sp wskazuje na pierwsze wolne miejsce
Operacje na stosie Kombinacje par liter (np. FD) stanowia modyfikatory, dołaczane do instrukcji LDM i STM. Można jedna instrukcja odkładać na stos wiele rejestrów STMFD sp!,{r0-r2} W rzeczywistości sa instrukcje wielokrotnego zapisu, np. LDMFD to LDMDA. Standardowe konwencje (ATPCS) zalecaja używanie pełnego stosu malejacego, czyli instrukcji LDMFD i STMFD. Poczawszy od ARMv5 stos musi być wyrównany do granicy 8 bajtów, bo wprowadzono instrukcje LDRD i STRD.
Instrukcje zamiany Instrukcja SWP zamienia zawartość pamięci z zawartościa rejestru, na przykład SWP r0,r1,[r2] wpisuje zawartość rejestru r1 do komórki pamięci o adresie w rejestrze r2. Do rejestru r0 trafia natomiast dotychczasowa zawartość komórki pamięci. Instrukcja ta jest atomowa: odczyt i zapis ma miejsce podczas pojedynczej operacji na szynie.
Instrukcje zamiany Aktywne czekanie na semaforze można zrealizować następujaco busy MOV r1,=semafor MOV r2,#1 SWP r3,r2,[r1] CMP r3,#1 BEQ busy
Przerwania Instrukcja SWI to przerwanie programowe. SWI 0x80 Zależnie od środowiska wywołuje ona emulator (np. KoMoDo) lub jadro systemu operacyjnego. Argumenty i wyniki przekazuje się w rejestrach.
Stan procesora Instrukcja MRS pobiera zawartość rejestru stanu procesora do zwykłego rejestru. Instrukcja MSR pozwala załadować do rejestru stanu procesora wybrany fragment z innego rejestru lub stałej. Przykład: zamaskowanie przerwań w trybie uprzywilejowanym MRS r1,cpsr BIC r1,r1,#0x80 MSR cpsr_c,r1 W instrukcji MSR przy rejestrze stanu podaje się modyfikatorem, które grupy pól maja być zmodyfikowane.
Stan procesora W instrukcji MSR przy rejestrze stanu podaje się w modyfikatorze, które grupy pól maja być zmodyfikowane: f: flagi warunków [24:31] c: sterowanie (maski przerwań, tryb) [0:7] x: bity rozszerzeń [8:15] s: status (zarezerwowane) [16:23]
Instrukcje koprocesorów Instrukcja CDP pozwala wywołać operację koprocesora Instrukcje MRC i MCR służa do przesyłania między rejestrami procesora i koprocesora. Instrukcje LDC i STC służa do przesyłania bloków pamięci między procesorem i koprocesorem.
Ładowanie stałych Ponieważ instrukcje ARM sa 32-bitowe, brak w nich miejsca na stałe 32-bitowe. Dozwolone sa tylko niektóre stałe, zwykle sa to Liczby bez znaku zapisane na 8-bitach Moga one dodatkowo być obrócone (w lewo lub prawo) o parzysta liczbę bitów Czyli pole stałej to 8 znaczacych bitów plus specyfikacja obrotu. Tak więc dozwolone sa stałe ale nie 5,0xff,0x104,0x0bc00000,0xe0000005 0x101,0x102
Ładowanie stałych Do ładowania innych liczb służa dwie (pseudo)instrukcje, realizowane jakoś istniejacymi instrukcjami. Instrukcja LDR może ładować stałe liczbowe LDR r3,=27321 Do ładowania adresu (etykiety w kodzie) służy instrukcja ADR r3,koniec Oczywiście adres to taki sam ciag bitów jak stała, ale kontekst użycia umożliwia inne oszustwa przy realizacji.
Ładowanie stałych Przykład: kopiowanie napisu main ADR r0,to ADR r1,from BL strcopy SWI 0x11 ;hipotetyczny exit from DCB "Pierwszy napis",0 to DCB "Drugi napis ",0 ALIGN strcopy LDRB r2,[r1],#1 STRB r2,[r0],#1 CMP r2,#0 BNE strcopy MOV pc,lr ;??? ;load byte, then update address ;store byte, then update address ;koniec?
Rozszerzenia w ARMv5 Zliczanie liczby wiodacych zer CLZ r1,r2 Arytmetyka z nasyceniem QADD r1,r2,r3 Nowa lepka flaga warunku Q. Mnożenie ze znakiem dla liczb 16-bitowych, z wskazywaniem modyfikatorem wybranych połówek rejestrów SMULTB r1,r2,r3 Przesłania 64-bitowe LDRD i STRD, operuja na parze rejestrów, pierwszy musi być parzysty.
Zliczanie zer Zliczanie zer w górnych pozycjach wyglada dziwnie, ale przydaje się do normalizacji zapisu stałopozycyjnego. Liczbę bez znaku w r0 można znormalizować przez CLZ r1,r0 MOV r0,r0,lsl r1 Wynik w r1, a w r2 wielkość przesunięcia. Dla liczb ze znakiem trudniej EOR r1,r0,r0,lsl #1 CLZ r1,r1 MOV r0,r0,lsl r1 ;pozycja ostatniego bitu znaku
Przekazywanie parametrów w kodzie Rejestr łacz acy upraszcza przekazywanie parametrów bezpośrednio w kodzie BL Copy DCD BufferLength ;długość w bajtach DCD Buffer1 ;adres początkowy DCD Buffer2 ;adres początkowy Po wywołaniu rejestr łacz acy zawiera adres poczatku bloku parametrów. Procedura (po ewentualnym zachowaniu rejestrów) pobiera parametry równocześnie ustawiajac rejestr łacz acy na właściwy adres Copy LDR R0,[LR],#4 LDR R1,[LR],#4 LDR R2,[LR],#4
Licznik rozkazów Z uwagi na istnienie potoku instrukcji w momencie wykonania licznik rozkazów pc (r15) wskazuje (co najmniej?) dwie instrukcje dalej. Oznacza to, że wartościa pc jest <adres bieżacej instrukcji>+8 (a w trybie Thumb +4)!