arm assembler początki

Witam. Przyglądam się kodm startowym do arm i nie rozumiem dlaczego raz stosuje się instrukcję ldr, a raz mov? Np w takim przypadku;

mov r0, #0x10

ldr r0, =0x10

Czym to wogóle się różni?

Dzięki za odpowiedz Pozdrawiam Paweł

Reply to
Pawel
Loading thread data ...

Pawel napisał(a):

MOV jest instrukcją wbudowaną w procesor (standardowo :-)) i ma sporo ograniczeń, np. nie umie załadować wartości 32-bitowej podanej w kodzie rozkazu prosto do rejestru. AFAIR dysponuje tylko wartością 8-bitową i ew. przesunięciem (czyli np. może załadować do rejestru wartości 0x50 i

0x5000 ale nie może 0x12345). Jest także instrukcja MVN, która ładuje do rejestru negację wartości obecnej w kodzie rozkazu - przez to można zapisać do rejestru np. wartość 0xffffffff.

LDR jest instrukcją przesyłającą wartość z pamięci do rejestru. Może ładować 32 bity (LDR), 16 bitów (LDRH) lub 8 bitów (LDRB). Może też dokonywać postinkrementacji wskaźnika lub predekrementacji, przesyłać wiele wartości naraz (do kilku rejestrów), być wykonywana warunkowo. Asembler ARMa jest naprawdę potężny. :)

LDR w połączeniu ze znakiem równości '=' i wartością stanowi magiczne makro, konwertowane przez asembler na najbardziej optymalną postać - instrukcję MOV lub MVN jeżeli się da albo załadowanie liczby z pamięci programu (stała do załadowania jest umieszczana nieco dalej, za bieżącą funkcją).

Czyli najbardziej optymalnie do ładowania stałych zawsze używać LDR ze znakiem '=' a asembler sam wybierze najlepsze rozwiązanie. Oczywiście nie ominiesz instrukcji MOV gdy chcesz zrobić proste przesłanie z rejestru do rejestru.

Reply to
Adam Dybkowski

Dzięki za odpowiedz. Rzeczywiście nie można załadować mov do r0 więcej niż #256.

Mam jeszcze jedno pytanie po przeczytaniu jakiegoś tutoriala nie do końca rozumiem wartość licznika rozkazów PC.

Napisane jest że w związku z pipeline przechowuje on zawsze adres rozkazu o 2 rozkazy do przodu względem tego który aktualnie wykonuje.

np: pierwsza instrukcjia powoduje załadowanie do R0 wartości (kodu rozkazu) spod adresu 0x8, a nie 0x00

0x00000000 ldr R0, [PC] 0x00000004 ldr R1,=1 0x00000008 ldr R2,=2

Z drugiej strony piszą że wykonanie instrukcji BL powoduje skok i zapisanie w LR wartości PC+4 (adresu powrotu, adresu następnej instrukcji). Czyli w poniższym przykładzie powinien być to adres 0x4. Ale przecież z wcześniejszego przykładu wynika że w PC jest aktualnie

0x8, a jak jeszcze dodać 4 to będzie 0xC.

0x00000000 bl skok

0x00000004 ldr r0,=1 0x00000008 ldr r1,=2 0x0000000C ldr r2,=3 skok:

Więc nie kumam co będzie zapisane w LR 0x4 czy 0xc? Czy przed powrotem ze "skok" trzeba zmniejszyć odpowiednio LR i dopiero załadować do PC czy bez zmniejszania?

Jeszcze raz dzięki za odpowiedź. Pozdrawiam Paweł

Reply to
Pawel

Pawel napisał(a):

[...]

Aby wrócić z funkcji wystarczy przeładować lr do pc i będzie dobrze. Czyli: "mov pc, lr". Z tego co pamiętam, wykorzystanie wartości rejestru pc (np. przy skoku albo skopiowaniu do innego rejestru) daje adres 8 bajtów dalej niż obecnie wykonywana instrukcja czyli kod "mov r0, pc" umieszczony pod adresem 0 spowoduje załadowanie do r0 stałej 8. Rozkaz taki jak "bl" działa poprawnie bo praca pipeline jest bardzo zależna od typu rozkazu (skoki są wykonywane dłużej niż np. instrukcja mov). Długo by tu tłumaczyć - proponuję ściągnąć dokładne opisy asemblera i architektury

7TDMI ze strony ARM'a i wgłębić się w rozdział dotyczący pipeline. Albo nie tracić na to czasu :) tylko przejść jak najszybciej na pisanie programów w języku C - a na spokojnie analizować kod wygenerowany przez kompilator aby obczaić "co i jak" się zwykle robi.
Reply to
Adam Dybkowski

Pawel wrote: ...

...

...

Instrukcja BL (branch and link) jest traktowana specjalnie. Podczas jej dekodowania od wartości (wcześniej) umieszczonej w LR (R14) jest odejmowana liczba 4 - właśnie po to, aby uprościć instrukcję powrotu z funkcji (return). Dzięki temu zamiast SUB PC,R14,#4 można napisać wprost MOV PC,R14. I dlatego przy powrocie z przerwania obowiązuje "siermiężne" SUB PC,R14,#4, bo mechnizm predekodowania (prefetch), z oczywistych powodów, nie działa w momencie wykonywania skoku do adresu procedury obsługi przerwania.

A tak wogóle (jakbyś chciał dowiedzieć się więcej) to jest to opisane w sekcji

6.2 ARM7TDMI Technical Reference Manual.

Pozdrawiam,

Reply to
Artur Lipowski

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.