Studium příkazového systému procesoru ramene. Studium systémového systému procesoru ramene Podmíněné provádění příkazů

Ahoj všichni!
Druhou činností jsem programátor Java. Poslední měsíce práce mě přinutily seznámit se s rozvojem Android NDK, a proto psát nativní aplikace na S. Zde jsem běžel do problematiky optimalizace Linux knihoven. Mnozí nebyli absolutně optimalizován pod rukou a vyschl procesor. Dříve, v podstatě jsem neměl program na assembler, tak to bylo nejprve těžké začít učit tento jazyk, ale přesto jsem se rozhodl to zkusit. Tento článek je napsán, tak mluvit, od začátečníků pro začátečníky. Pokusím se popsat tyto základy, které již studovaly, doufám, že to někdo zaujme. Kromě toho budu potěšen konstruktivní kritikou odborníků.

Úvod
Takže, na začátek pochopím, co je paže. Wikipedia poskytuje takovou definici:

Architektura paže (pokročilý RISC stroj, Acorn RISC stroj, vylepšený RISC stroj) - rodina licencovaných 32-bitových a 64bitových mikroprocesorových jader pro rozvoj omezené ramena. Společnost se zabývá vývojem jader a nástrojů pro ně (kompilátory, ladicí nástroje atd.), Vydělávat licencování architektury až po výrobce třetích stran.

Pokud někdo ví, nejvíce mobilní zařízeníTablety jsou uvedeny přesně na této architektuře procesorů. Hlavní výhodou této rodiny je nízká spotřebaVzhledem k tomu, které se často používají v různých vestavěných systémech. Architektura vyvinula v průběhu času, a počínaje ARMv7 3 profily byly definovány: 'A' (Application) - aplikace, 'R' (Real Time) - v reálném čase, 'M' (mikrořadič) je mikrořadič. Historie vývoje této technologie a dalších zajímavých dat, které můžete číst v Wikipedii nebo Google na Internetu. Rameno podporuje různé režimy provozu (palce a rameno, navíc naposledy Thumb-2 se objevil, což je směs ramene a palce). V tomto článku zvažte samotný režim ramene, který provádí 32bitovou sadu příkazů.

Každý procesor ramene je vytvořen z následujících bloků:

  • 37 registrů (z nichž pouze 17 jsou viditelné během vývoje)
  • Aritmetické a logické zařízení (allu) - provádí aritmetické a logické úkoly
  • Barrel SHIFTER - zařízení vytvořené pro přesun datových bloků do určité množství bitů
  • CP15 - speciální systém ovládání ramene coprocesorů
  • Dekodér instrukcí - Zabývající se pokyny pro konverze v sekvenci mikro-operací
Nejedná se o všechny složky paže, ale prohloubení v procesorech debristů nevzniká téma tohoto článku.
Provedení dopravníku (spuštění potrubí)
Procesory ramene používají 3-stadionový dopravník (počínaje Arm8 byl implementován 5-stadionový dopravník). Zvažte jednoduchý dopravník na příkladu procesoru Arm7TDMI. Provedení každé instrukce se skládá ze tří kroků:

1. Stage vzorkování (F)
V této fázi pokyny pocházejí z RAM do procesorového dopravníku.
2. Stage dekódování (D)
Pokyny jsou dekódovány a rozpoznány podle jejich typu.
3. Stage provedení (E)
Data jsou přijata v ALU a jsou prováděna a získaná hodnota je zaznamenána v určeném registru.

Při vývoji je nutné vzít v úvahu, že existují pokyny, které používají více prováděcích cyklů, například zatížení (LDR) nebo úložiště. V tomto případě je krok provedení (E) rozděleno do kroků (E1, E2, E3 ...).

Podmíněný výkon
Jedním z nejdůležitějších funkcí paže assembler je podmíněným prováděním. Každá instrukce může být provedena podmíněně a pro toto je použito přípony. Pokud je přípona přidána do názvu instrukce, pak předtím, než jej provedete, nastane kontrola parametrů. Pokud parametry nesplňují podmínku, instrukce není provedena. Přípona:
MI - záporné číslo
Pl - pozitivní nebo nula
Al - Proveďte pokyny vždy
Stačí podmíněného provádění je mnohem více. Zbývající přípony a příklady čtené v oficiální dokumentaci: Dokumentace ARM
A teď je čas zvážit ...
Základy syntaxe paže assembler
Ti, kteří pracovali s assemblerem, tuto položku mohou skutečně přeskočit. Pro všechny ostatní popíšu základy práce s tímto jazykem. Každý program na assembleru se skládá z pokynů. Instrukce je vytvořena tímto způsobem:
(štítek) (instrukce | operandy) (@ \u200b\u200bkomentář)
Štítek je volitelný parametr. Instrukce - přímo MNEMONICS Pokyny pro procesor. Základní pokyny a jejich použití budou demontovány dále. Operandy - konstanty, adresy registrů, adresy v paměť s náhodným přístupem. Komentář je volitelný parametr, který nemá vliv na provedení programu.
Jména registrů
Následující registry jsou povoleny:
1.R0-R15.

3.v1-V8 (variabilní registry, s R4 od R11)

4.SB a SB (statický registr, R9)

5.SL a SL (R10)

6.FP a FP (R11)

7.ip a IP (R12)

8.SP a SP (R13)

9.LR a LR (R14)

10.PC a PC (Počítadlo softwaru, R15).

Proměnné a Kostans.
V paže assembler lze použít jako každý (prakticky), proměnné a konstanty. Jsou rozděleny do těchto typů:
  • Numeric.
  • hlavolam
  • Tětiva
Číselné proměnné jsou inicializovány takto:
SETA 100; Numerická proměnná "A" je vytvořena s hodnotou 100.
Proměnné řetězce:
Improb sady "doslova"; Provozní proměnná je vytvořena s hodnotou "Literal". POZORNOST! Hodnota proměnné nemůže překročit 5120 znaků.
V logických proměnných se odpovídajícím způsobem používají pravdivé a nepravdivé hodnoty.
Příklady instrukcí paže assembler
V této tabulce jsem shromáždil základní pokyny, které budou vyžadovány pro další rozvoj (v základní fázi :) :) :)

Chcete-li upevnit použití základních pokynů, pojďme napsat několik jednoduchých příkladů, ale nejprve budeme potřebovat rameno Toolchain. Pracuji v Linuxu, takže si vybral: frank.harvard.edu/~coldwell/toolchain (rameno-neznámý-linux-gnu nástroj). To je jednodušší pro jednoduché, stejně jako jakýkoli jiný program na Linuxu. V mém případě (Russian Fedora) bylo nutné nainstalovat pouze pakety RPM z webu.
Teď je čas psát nejjednodušší příklad. Program bude absolutně zbytečný, ale co je nejdůležitější, co bude fungovat :) Zde je kód, který vám doporučuji:
Start: @ volitelný řetězec, označující začátek programu MOV R0, # 3 @ Georgis v registru R0 Hodnota 3 mov R1, # 2 @ @ @ @ @ @ @ @ , R0 @ Fold R0 a R1, odpověď je zaznamenána v R2 Mul R3, R1, R0 @ Vynásobte hodnotu registru R1 na hodnotu registru R0, odpověď je zaznamenána v R3 STOP: B Stop @ Program Ukončení řetězce
Před přijetím doplňte program.
/ Usr / rameno / bin / paže-neznámý-linux-gnu-as -o arm.o Arm.O Arm.O ARM.O / USR / rameno / bin / arm-neznámý-linux-gnu-ld -ttext \u003d 0x0 -o \u200b\u200brameno. Elf rameno .o / usr / rameno / bin / paže-neznámý-linux-gnu-objcopy -o binární paže.V rameno.bin
(kód v souboru ARM.S a Toolchain v mém případě spočívá v adresáři / usr / ramen / bin /)
Pokud všechno šlo úspěšně, budete mít 3 soubory: Arm.s (vlastně kód), Arm.O, Arm.Fel, Arm.bin (vlastně program). Za účelem testování provozu programu nemusí být nutně mít vlastní zařízení pro rameno. Stačí nainstalovat Qemu. Pro referenci:

QEMU - volný program Otevřený zdroj pro emulaci hardwaru různých platforem.

Zahrnuje emulaci procesory Intel. X86 a I / O zařízení. Může emulovat 80386, 80486, Pentium, Pentium Pro, AMD64 a další X86 kompatibilní se procesory; PowerPC, paže, mipy, SPARC, SPARC64, M68K - pouze částečně.

Pracuje na slabice, FreeBSD, Freedos, Linux, Windows 9x, Windows 2000, Mac OS X, QNX, Android atd.

Tak to bude trvat Qemu-System-rameno pro emulaci paže. Tento balíček je v Yum, aby ti, kteří mají Fedory, nemůžete obtěžovat a jen splnit příkaz:
Yum Install Qemu-System-Arm

Dále musíte spustit emulátor ramene, takže splňuje náš program ARM.BIN. Chcete-li to provést, vytvořte soubor flash.bin, který bude paměť flash pro QEMU. Udělej to velmi jednoduché:
DD pokud \u003d / dev / nula z \u003d flash.bin bs \u003d 4096 počet \u003d 4096 dd pokud \u003d arm.bin of \u003d flash.bin bs \u003d 4096 conv \u003d notrans
Nyní loď Qemu s výsledným flash paměť:
QEMU-SYSTEM-ARM -M CONNEX -PFLASH FLASH.BIN -Nographic -Serial / dev / null
Na výstupu dostanete něco takového:

$ QEMU-system-ARM -m Connex -Pflash Flash.bin -Nographic -Serial / dev / null
QEMU 0.15.1 Monitor - Typ "Nápověda" pro více informací
(QEMU)

Naše program ARM.BIN měl změnit hodnoty čtyř registrů, proto ověřit správnost práce, podívejme se na tyto většiny registrů. To se provádí velmi jednoduchý příkaz: Info Registry
Na výstupu uvidíte všech 15 ramenných registrů, se čtyřmi z nich budou upraveny hodnoty. Zkontrolujte :) Hodnoty registrů se shodují s těmi, které lze očekávat po provedení programu:
(QEMU) info registruje R00 \u003d 00000003 R01 \u003d 00000002 R02 \u003d 00000005 R03 \u003d 00000006 R04 \u003d 00000000 R05 \u003d 000000 R06 \u003d 00000000 R07 \u003d 000000 R08 \u003d 000000 R09 R11 \u003d 00000000 R12 \u003d 00000000 R13 \u003d 00000000 R14 \u003d 00000000 R14 \u003d 00000000 R15 \u003d 00000010 PSR \u003d 400001d3 -z-- A SVC32

P.S. V tomto článku jsem se snažil popsat základy programování na assembleru. Doufám, že sis to užil! To stačí, aby se dále ponořil do nečistot tohoto jazyka a zapište programy na něm. Pokud všechno funguje, budu psát dále o tom, co poznávám. Pokud jsou chyby, neveďte prosím, protože jsem začátečník v assembleru.

Nejprve Paže Docela neobvyklý assembler (pokud odejdete do důchodu x86., MCS51. nebo Avr.). Má však docela jednoduchou a logickou organizaci, takže je rychle absorbována.

Dokumentace v ruštině na assembleru je zcela malá. Dokážu poradit jít na 2 odkazy (možná najdete víc a řekni mi? Budu vděčný.):
Architektura a systém týmů Riss procesorů rodiny Arm - http://www.gaw.ru/html.cgi/txt/doc/micros/arm/index.htm
Chápeme paže assembler, od výrobků "GBA ASM", Mike H, Per. Aquila - http://wasm.ru/series.php?sid\u003d21.

Opravdu mi pomohl poslední odkaz, rozptýlil fog \u003d). Druhý, který může pomoci dobře - je, že je to dost, kompilátor C IAR EMBEDDED WORKBENCH PRO PRŮM (dále jen Simple. IAR EW RAM.). Faktem je, že ví, jak sestavit C-kód v assembleru kód, který, podle pořadí, je také snadno sestaveného assembler IAR v objektového kódu, případ (stejně jako všechny sebeúcty kompilátorem, nicméně) Kompilovat kód C do kódu assembleru. Proto neexistuje nic lepšího napsat nejjednodušší funkci na C, zkompilovat ji do assembleru a okamžitě bude jasné, jaký typ montážního příkazu dělá to, co argumenty prošly a jak je výsledek vrácen. Zabijete dva zajíce najednou - vyučil assembleru a zároveň získáte informace jak intergreed assembler kód do projektu na C. jsem trénoval na funkci pro výpočet CRC16, a jako výsledek, získal jeho plnou verzi na assembler.

Zde je zdrojová funkce na C (U16 znamená nepodepsané krátké, U32 - unsigned Int, U8 - unsigned char):
// soubor crc16.c.
U16 CRC16 (Void * DataBuf, U32 Velikost)
{
U16 TMPWORD, CRC16, IDX;
U8 bitcnt;
#Define crc_poly 0x1021;

CRC16 \u003d 0;
idx \u003d 0;
Zatímco (velikost! \u003d 0)
{
/ * Masing XOR Senior Byte CRC16 a vstupní bajt * /
TMPWORD \u003d (CRC16 \u003e\u003e 8) ^ (* (((U8 *) Databuf) + IDX));
/ * Výsledek píšeme do senior byte crc16 * /
TMPWORD.<<= 8;
CRC16 \u003d TMPWORD + (0x00FF & CRC16);
pro (bitcnt \u003d 8; bitcnt! \u003d 0; bitcnt--)
{
/ * Zkontrolujte senior baterie CRC * /
IF (CRC16 & 0x8000)
{
CRC16.<<= 1;
CRC16 ^ \u003d CRC_POLY;
}
JINÝ.
CRC16.<<= 1;
}
IDX ++;
Velikost--;
}
Vrátit CRC16;
}

Proveďte generující kód EAR EW ARM assembler je velmi snadný. V možnostech souborů CRC16.C (přidané do projektu) Přepsat zděděné nastavenía pak na seznamu položil 3 tanky - Výstupní assembler soubor., Zahrnout zdroj. a Zahrnout informace o volání (Ačkoli poslední DAW, pravděpodobně, nemůžete dát - generuje banda zbytečné Cfi.-Déžové). Po kompilaci, soubor složky \\ EWP \\ AT91SAM7X256_SRAM \\ LIST \\ CRC16.s dopadlo. Tento soubor lze také snadno přidat do projektu, jako je C-soubor (to bude normálně kompilovat).

Samozřejmě, když jsem sklouzl C-kompilátor. Uncircumcised verze C-Code, dal mi takový seznam assembleru, že jsem nic nechápal. Ale když všichni C-operátoři byli vyhozeni z funkce, s výjimkou jednoho, to bylo jasnější. Pak krok za krokem přidali C-operátory, a dále, co se stalo:

; CRC16.S. Soubor
Jméno CRC16.
Public CRC16.

Crc_poly equ 0x1021.

Sekce `` .Text`: kód: noroot (2)
Paže

// U16 CRC16 (Void * DataBuf, U32 Velikost)
; R0 - výsledek návratu, CRC16
; R1 - parametr velikosti
R2 - parametr databuf (byl u vchodu do R0)
R3, R12 - Dočasné registry

CRC16:
Stiskněte (R3, R12); TYK, zjistil, že R3 a R13 Save
; není nezbytné. Ale rozhodl jsem se udržet
; happening.
MOVS R2, R0; NYNÍ R2 \u003d\u003d DATABUF
MOV R3, # + 0
MOVS R0, R3; CRC16 \u003d 0
CRC16_LOOP:
CMP R1, # + 0; Všechny bajty byly zpracovány (velikost \u003d\u003d 0)?
BEQ CRC16_RETURN; pokud ano, pak
LSR R3, R0, # + 8; R3 \u003d CRC16 \u003e\u003e 8
LDRB R12, R12 \u003d * DATABUF
EOR R3, R3, R12; R3 \u003d * DATABUF ^ HIGH (CRC16)
LSL R3, R3, # + 8; R3<<= 8 (tmpWord <<= 8)
A R0, R0, # + 255; CRC16 & \u003d 0x00ff
Přidejte R0, R0, R3; CRC16 \u003d TMPWORD + (0x00FF & CRC16)
MOV R12, # + 8; bitcnt \u003d 8
CRC16_BIT_LOOP:
BEQ CRC16_NEXT_BYTE; bitcnt \u003d\u003d 0?
TST R0, # 0x8000; Ne všechny bity jsou zpracovány.
BEQ CRC16_BIT16ZE; kontrola senior CRC16 bit.
LSL R0, R0, # + 1; CRC16<<= 1
MOV R3, # + (Low (CRC_POLY)); CRC16 ^ \u003d CRC_POLY
ORR R3, R3, # + (HIGH (CRC_POLY)<< 8) ;
EOR R0, R3, R0;
B crc16_next_bit.

CRC16_BIT16ZERO:
LSL R0, R0, # + 1; CRC16<<= 1
CRC16_NEXT_BIT:
Subs R12, R12, # + 1; bitcnt--
B crc16_bit_loop;

CRC16_NEXT_BYTE:
Přidat R2, R2, # + 1; databuf ++
Subs R1, R1, # + 1; velikost--
B crc16_loop; cyklus pro všechny bajty

CRC16_RETURN:
POP (R3, R12); RESTORE REARSTERS
BX LR; Výstup z podprogramu R0 \u003d\u003d CRC16

Kompilátor C od společnosti C přinutit překvapivě dobrý kód. Úplně jsem ho podařilo optimalizovat. Vyhodil jsem jen nadbytečný dočasný registr, který chtěl použít kompilátor (z nějakého důvodu vzal jako nadměrný dočasný registr LR, i když R3 a R12 byly dost), a také odstranil pár zbytečných týmů kontroly čítačů a vystavujících příznaků (jednoduše) Přidání SFIX S do požadovaných týmů).

Procesory CISC jsou prováděny pro jeden tým poměrně složitých operací, včetně aritmetických a logických operací na obsahu paměťových buněk. Příkazy procesoru CISC mohou mít různé délky.

Naopak RISC má relativně jednoduchý systém týmů s jasným dělením podle typu operace:

  • práce s pamětí (přečtěte si z paměti na registry nebo záznam z registru registrů)
  • zpracování dat v registrech (aritmetické, logické, datové posuny vlevo / vpravo nebo rotující bit v registru),
  • společné nebo bezpodmínečné přechody na jiné adresy.

Zpravidla (ale ne vždy, a pouze v případě, že kód programu zasáhl do paměti mezipaměti regulátoru), jeden příkaz je proveden jedno procesorové hodiny. Rameno Opraveno procesorové délky procesoru - 4 bajty (jedno počítačové slovo). Ve skutečnosti, moderní ARM procesor může přejít na jiné druhy provozu, například v režimu palcem, když je délka příkaz stává 2 bajty. To vám umožní vytvořit kód kompaktnější. Nicméně, v tomto článku tento režim nepovažujeme, protože v procesoru Amber ARM V2A není podporován. Ze stejného důvodu nebudeme v úvahu takové režimy, jako je Jazelle (optimalizováno pro provádění kódu Java) a nebude zvažovat neonové příkazy - příkazy operací na více datech. Studujeme čistý systém příkazů ARM.

Registry procesoru ramene.

Procesor ramene má několik sad registrů, ze kterých je v tuto chvíli k dispozici pouze na programátorovi 16. Existuje několik režimů procesoru v závislosti na provozním režimu, odpovídající banka registrů je vybrána. Tyto režimy provozu:

  • režim aplikace (USR, uživatelský režim),
  • režim supervizora nebo režim operačního systému (SVC, režim supervizor),
  • režim přerušení zpracování (IRQ, režim přerušení) a
  • firq, režim zpracování režimu rychlého přerušení.

To znamená, že když dojde k přerušení, procesor sám projde na adresu programu pro handler přerušení a automaticky "přepínače" registrovat banky.

Procesory ramene starších verzí jiných než výše uvedených režimů provozu mají více dalších režimů:

  • Zrušit (slouží k zpracování výjimek přístupu k paměti),
  • Undefined (používá se k implementaci koprocesoru k programátoru) a
  • způsob ovlivněných úkolů operačního systému systému.

Neexistují žádné další tři režimy v procesoru Amber Arm ARM V2A.

Pro jantarové rameno V2A může být soubor registrů reprezentován následovně:

Registry R0-R7 jsou stejné pro všechny režimy.
Registry R8-R12 jsou běžné pouze pro USR, SVC, IRQ režimy.
Registr R13 je ukazatel zásobníku. Je ve všech režimech jeho vlastní.
Zaregistrujte R14 - Zpětný registr z podprogramu, stejně jako jeho vlastní režimy.
Registr R15 je ukazatel na spustitelné příkazy. Je běžné pro všechny režimy.

Je vidět, že režim Firq je nejvíce izolovaný, má většinu svých vlastních registrů. To se děje tak, aby bylo možné zpracovávat některé velmi kritické přerušení bez uložení registrů na zásobníku bez ztráty času.

Zvláštní pozornost by měla být věnována registru R15, je to PC (Counter Program) - ukazatel na spustitelné příkazy. Můžete provádět různé aritmetické a logické operace na jeho obsah, čímž provede provedení programu na jiné adresy. Je však pro rameno V2A procesor, který implementován v jantarovém systému, má některé jemnosti při interpretaci bitů tohoto registru.

Faktem je, že v tomto procesoru v registru R15 (PC), kromě skutečného ukazatele na spustitelné příkazy obsahuje následující informace:

Bity 31:28 - Vlajky výsledku aritmetické nebo logické operace
Bity 27 - Maska přerušení IRQ, přerušení je zakázáno, když je nainstalován bit.
Bity 26 - Firq Interupervová maska, rychlé přerušení jsou zakázány, když je nainstalován bit.
Bity 25: 2 - Vlastně ukazatel na příkazů programů pouze 26 bitů trvá.
Bity 1: 0 - aktuální režim provozu procesoru.
3 - Supervisor.
2 - přerušení
1 - Rychlé přerušení
0 - Uživatel.

Ve starších procesoru ramene jsou všechny vlajky a servisní bity umístěny v samostatných registrech. Současný registr stavu programu(CPSR) a uložený registr status programu (SPSR), pro přístup, ke kterému existují samostatné speciální příkazy. To se provádí za účelem rozšíření dostupného adresního prostoru pro programy.

Jedním z problémů s rozvojovými montážními pažemi je alternativními názvy některých registrů. Takže, jak bylo řečeno výše, R15 je stejný PC. Tam je stále R13 - to je stejný sp (ukazatel zásobníku), R14 je LR (Link Register) - registr návratové adresy z postupu. Kromě toho, R12 je stejná IP (intra-procedury -call Scratch Register), který používal kompilátory se zvláštním způsobem pro přístup k parametrům v zásobníku. Takové alternativní pojmenování někdy se zaměňuje, když se podíváte na kodex programu někoho jiného - existují také ty a tyto označení registrů.

Funkce provedení kódu.

V mnoha typech zařízení procesoru (například X86) lze provést pouze přechod na jinou adresu programu. V paži není. Každý příkaz procesoru ramene lze provádět nebo provádět podmínkou. To vám umožní minimalizovat počet přechodů programu, a proto efektivněji používat procesor dopravníku (potrubí).

Co je potrubí? Jeden příkaz procesor je nyní vybrán z kódu programu, předchozí je již dekódován a předchozí je již proveden. To je v případě 3-stadionu Amber A23 procesorového dopravníku, který používáme v našem projektu platby Squirrels2moscow2. . Modifikace procesoru Amber A25 má 5-stadionový dopravník, je ještě účinnější. Ale je tu jeden velký, ale. Příkazy přechodu přinutily procesor vyčistit potrubí a znovu ji vyplnou. Nový tým je tedy vybrán, ale stále není nic dekódovat a ještě více nesplňují. Účinnost provedení kódu při častých přechodech spadá. V moderních procesorech existují všechny mechanismy přechodu predikce, které nějakým způsobem optimalizují obsah dopravníku, ale v našem procesoru není nikdo. V každém případě, rameno vstoupilo moudře, což umožňuje provádět každý tým podmíněný.

V ARM procesoru, v příkazu jakýchkoliv čtyř bitů typu, provedení příkazu podmínky jsou zakódovány ve starších čtyř bitů příkazového kódu:

Celkem procesor 4 podmínky vlajek:
. Negativní - výsledek operace se ukázalo negativní,
. Nula - výsledek je nula,
. Proveďte - při provádění operace s nepodepsanými čísly došlo k převodu,
. Přetečení - Při provádění operace s čísly ikon došlo k přetečení, výsledek není uveden v registru)

Tyto 4 vlajky tvoří mnoho možných kombinací stavu:

Kód Přípona Hodnota Vlajky
4 "H0. eq. Rovnat se. Z Nastavit.
4 "H1. ne. Není roven Z jasné
4 "H2. cS / HS. Nést sadu / nepodepsané vyšší nebo stejné C Nastavit.
4 "H3. cC / LO. Nést jasno / nepodepsané lem C jasný
4 "H4. mi. Mínus / negativní N Sada.
4 "H5. pL. Plus / kladný nebo nula N jasný
4 "H6. vs. Přetékat. V Nastavit.
4 "H7. vc. Žádný přetečení. V jasný
4 "H8. aHOJ Vyšší. C nastavit a z jasné
4 "H9. ls. Nižší nebo stejné C Clear nebo Z
4 "ha. ge. Podepsán větší nebo rovný N \u003d\u003d V.
4 "Hb. laskavost Podepsáno méně než. N! \u003d V
4 "HC. gt. Podepsáno větší než. Z \u003d\u003d 0, n \u003d\u003d v
4 "HD. le. Podepsáno méně než nebo rovno Z \u003d\u003d 1 nebo n! \u003d V
4 "On. al. Vždy (bezpodmínečné)
4 "HF. - Neplatný stav.

Jednou z nich následuje další obtíž ke studiu příkazů procesoru ramene - množinu přípon, které lze přidat do příkazového kódu. Například, navíc za předpokladu, že je nastavena vlajka Z - to je příkaz adteq jako add + eq přípona. Jděte do podprogramu, pokud vlajka n \u003d 0 je BLPL AS BL + SUFIFIX pl.

Vlajky (Negativní, nula, nést, přetečení) Stejný není vždy nastavena v aritmetické nebo logické operace, jak se to děje v procesoru X86, ale pouze tehdy, když programátor chce. Za tímto účelem existuje další přípona pro velitelské mnemonici: "S" (v příkazovém kódu je kódován o bit 20). Přidání přídavného týmu tedy nemění příznaky a příkaz Přidat změní příznaky. A možná je stále podmíněný tým doplnění, ale které mění vlajky. Například: AddGts. Je zřejmé, že počet možných kombinací příkazů příkazů s různými SOFFIXY podmíněných provedení a instalace příznaků činí kód montáže ramene procesoru ramene velmi zvláštního a obtížně číst. V průběhu času si však na vás zvyknete a začnete tento text pochopit.

Aritmetické a logické operace (zpracování dat).

Procesor ramene může provádět různé aritmetické a logické operace.

Ve skutečnosti je čtyřlůžkový operační kód (OPCODE) obsažen v bitech příkazu procesoru.

Jakákoli operace se provádí nad obsahem registru a tzv. Shifter_operand. Výsledek operace je umístěn v registru. Čtyřlůžkový RN a RD jsou indexy registrů v aktivní bance procesoru.

V závislosti na bitu I 25, Shifter_operand je ošetřen buď jako numerickou konstantou nebo jako index druhého operačního registru a dokonce i přesunu přesunu přes hodnotu druhého operandu.

Jednoduché příklady příkazů assembler budou vypadat například takto:

přidejte R0, R1, R2 @ místo v R0 registrovat součet hodnot registrů R1 a R2
sub R5, R4, # 7 @ pozice v registru R5 Rozdíl (R4-7)

Operované operace jsou kódovány následujícím způsobem:

4 "H0 a logické a RD: \u003d RN a Shifter_Operand
4 "H1 EOR Logický s výjimkou nebo RD: \u003d RN XOR Shifter_Operand
4 "H2 Sub aritmetika Odčítání RD: \u003d RN - Shifter_Operand
4 "H3 RSB Aritmetic Reverse Odčítání RD: \u003d Shifter_Operand - RN
4 "H4 Přidejte aritmetické přidávání Rd: \u003d Rn + Shifter_operand
4 "H5 ADC Aritmetic Addition Plus PD přenosový vlajka: \u003d RN + Shifter_Operand + Carry Flag
4 "H6 SBC Aritmetic Subtraction s RD: \u003d RN - Shifter_Operand - ne (nést vlajku)
4 „H7 RSC aritmetické Inverzní odčítání s RD: \u003d Shifter_operand - RN - NE (Carry Flag)
4 "H8 TST Logické a, ale bez zapamatování výsledku, pouze vlajky Rn a Shifter_operand S bit vždy nastavit
4 "H9 TEQ Logický exkluzivní nebo, ale bez zapamatování výsledku, pouze vlajky Rn Eor Shifter_operand se změní
S bit vždy nastaven
4 "srovnání HA CMP, nebo spíše aritmetické odčítání bez zapamatování výsledku, pouze vlajky Rn - Shifter_Operand S bit vždy nastavit
4 "HB CMN Srovnání inverzního nebo spíše aritmetického přidávání bez zapamatování výsledku, pouze příznaky RN + Shifter_operand S bit vždy nastavit
4 "HC ORR Logický nebo Rd: \u003d RN nebo Shifter_Operand
4 "HD MOV Kopírování RD: \u003d Shifter_operand (žádný první operand)
4 "HE bic reset bitů rd: \u003d rn a ne (shifter_operand)
4 "HF MVN kopírování Invertance Rd: \u003d Ne Shifter_Operand (žádný první operand)

Slavnostní řazení.

V procesoru ramene existuje speciální schéma "Slavnostní posuvník", který umožňuje jeden z operandů pohybovat nebo nasazení na zadaný počet bitů před jakoukoliv aritmetickou nebo logickou operací. Jedná se o poměrně zajímavou funkci procesoru, který vám umožní vytvořit velmi efektivní kód.

Například:

@ Násobení o 9 je násobení čísla na 8
@ Posunutím vlevo od 3 bitů plus jiné číslo
přidejte R0, R1, R1, LSL # 3 @ r0 \u003d R1 + (R1<<3) = r1*9

@ Násobení o 15 je násobení o 16 mínus čísla
rSB R0, R1, R1, LSL # 4 @ r0 \u003d (R1<<4)-r1 = r1*15

@ Přístup k tabulce 4 bajtových slov, kde
@ R1 je základní adresa tabulky
@ R2 je index prvku v tabulce
ldr r0,

Kromě logického posunu do levého LSL je stále logický posun k pravému LSR a aritmetický posun doprava ASR (posun se znakem čísla, senior bit je násoben vlevo ve stejnou dobu s posunem).

Stále je stále rotace bitů ROR - bity jsou předány doprava a ty, které jsou prodlouženy - pohyb vlevo.
Tam je posun jeden bit přes příznak c je příkaz rrx. Hodnota registrace je posunuta doprava na jeden bit. Vlevo ve seniorské kategorii registru načte vlajku

Posun lze provést ne pevným konstantním číslem, ale hodnotou třetího operačního registru. Například:

přidejte R0, R1, R1, LSR R3 @ je R0 \u003d R1 + (R1 \u003e\u003e R3);
přidejte R0, R0, R1, LSR R3 @ je R0 \u003d R0 + (R1 \u003e\u003e R3);

Tak, Shifter_operand je to, co popisujeme v příkazech assembler, například jako "R1, LSR R3" nebo "R2, LSL # 5".

Nejzajímavější je, že použití posunů v operacím stojí nic. Tyto posuny (obvykle) nejsou vynakládány další poplatky a je velmi dobré pro výkon systému.

Použijte numerické operandy.

Aritmetické nebo logické operace mohou používat jako druhý operand nejen obsah registru, ale také numerická konstanta.

Bohužel existuje jeden důležitý omezení. Vzhledem k tomu, že všechny příkazy mají pevnou délku 4 bajtů (32 bitů), pak "libovolné" číslo nelze v něm zakódovat. V operačním kódu a SO 4 bity jsou obsazeny kódem stavu provedení (Cond), 4 bity na samotný operační kód (OPCODE), pak 4 bity - registr RD přijímače a další 4 bity - registru první Operand RN, plus více různých příznaků I 25 (jen odkazuje na numerickou konstantou v operačním kódu) a s 20 (instalace příznaků po operaci). Celkem, pouze 12 bitů zůstává pro možné konstantní, tzv. Shifter_Operand - viděli jsme to vyšší. Vzhledem k tomu, že 12 bitů může kódovat pouze čísla v úzkém rozsahu vývojářů ramene procesoru, rozhodli se vytvořit konstantní kódování následujícím způsobem. Dvanáct bitů Shifter_Operand je rozdělen do dvou částí: čtyřbitový indikátor otáčení kódovat_imm a skutečná osmbitová číselná hodnota IMM_8.

Konstanta procesoru ramene je určena osmibitovým číslem v rámci 32bitového čísla, nasazeného vpravo na sudý počet bitů. Tj:

iMM_32 \u003d IMM_8 ROR (Encode_imm * 2)

Ukázalo se, že to bylo moudré. Ukazuje se, že ne každý počet konstanta lze použít v příkazech assembler.

Může být napsán

přidat R0, R2, # 255 @ konstanta v desetinné formě
přidat R0, R3, # 0xFF @ konstanta v hexadecimálním

od roku 255 je v rozmezí 8 bitů. Tyto příkazy budou kompilovány takto:

0: E28200FF Přidání R0, R2, # 255; 0xff.
4: E28300FF Přidání R0, R3, # 255; 0xff.

A můžete dokonce psát

přidat R0, R4, # 512
přidat R0, R5, 0x650000

Kompilovaný kód bude takto:

0: E2840C02 Přidání R0, R4, # 512; 0x200.
4: E2850865 Přidat R0, R5, # 6619136; 0x650000.

V tomto případě se samozřejmě číslo 512 samozřejmě nehodí do bajtu. Představujeme to v hexadecimální podobě 32'H00000200 a zjistíme, že je to 2 rozloženo napravo na 24 bitů (1 ROR 24). Rotační koeficient je dvakrát menší než 24, tj. 12. Tak to dopadne Shifter_operand \u003d (4'HC, 8'H02) - jedná se o dvanáct mladších bitů týmu. Také s číslem 0x650000. Pro něj Shifter_operand \u003d (4'H8, 8'H65).

Je jasné, že je nemožné psát

přidat R0, R1, # 1234567

nebo nelze napsat

mOV R0, # 511

vzhledem k tomu, že zde číslo nefunguje ve formuláři IMM_8 a Encode_imm - faktor otáčení. Kompilátor assembleru vydá chybu.

Co dělat, když konstanta nemůže být přímo kódována v Shifter_operand? Musíte udělat nějaké triky.
Například můžete nejprve nahrát číslo 512 do volného registru a poté odečíst jednotku:

mOV R0, # 511
sub R0, R0, # 1

Druhý způsob, jak nahrát do registru konkrétní číslo je přečíst od speciálně rezervované proměnné v paměti:

ldr r7, my_var
.....
my_var: .word 0x123456

Nejjednodušší způsob, jak psát takto:

lDR R2, \u003d 511

V tomto případě (věnujte pozornost znaku "\u003d"), pokud konstanta může být reprezentována jako IMS_8 a kódování_imm, pokud lze zadat do 12 bitů Shifter_operand, kompilátor Assembler kompilátor automaticky kompiluje LDR na příkaz MOV. Pokud však číslo nelze tak prezentovat, kompilátor si vyhrazuje paměťovou buňku v programu pro tuto konstantu a samotná položka název je název a kompiluje příkaz v LDR.

Tak jsem to napsal:

ldr r7, my_var
LDR R8, \u003d 511
LDR R8, \u003d 1024
LDR R9, \u003d 0x3456
........
My_var: .word 0x123456

Po přijetí kompilace:

18: E59F7030 LDR R7 ,; padesátka
1C: E59F8030 LDR R8 ,; 54.
20: E3A08B01 MOV R8, # 1024; 0x400.
24: E59F902C LDR R9 ,; 58.
.............
00000050 :
50: 00123456. Sword 0x00123456
54: 000001FF. Sword 0x000001ff
58: 00003456. Sword 0x00003456

Upozorňujeme, že kompilátor používá adresování paměťových buněk vzhledem k registru PC (je to R15).

Čtení paměťové buňky a registru záznamů v paměti.

Jak jsem již napsal výše, procesor ramene může provádět aritmetické nebo logické operace pouze na obsah registrů. Data pro operace, kterou potřebujete ke čtení z paměti a znovu zapisovat operace v paměti. K tomu jsou speciální příkazy: LDR (pravděpodobně z "Zatížení registr") a STR (pravděpodobně "Store Regi Ster") pro nahrávání.

Zdálo by se - pouze dva týmy, ale ve skutečnosti mají mnoho variant. Stačí se podívat na metody procesoru Amber ARM LDR / STR, abyste zjistili, kolik pomocných bitů L 20, W 21, B 22, U 23, P 24, I 25 - a určují specifické chování týmu:

  • Bit L 20 definuje záznam nebo čtení. 1 - LDR, čtení, 0 - Str, záznam.
  • Bit B 22 Definuje číst / napsat 32bitové slovo nebo 8bitové bajty. 1 znamená operaci s bajtem. Při čtení bajtu v registru jsou vyšší bity registru resetovány.
  • Bit I 25 Definuje použití ofsetového pole. Pokud i 25 \u003d\u003d 0, pak je ofset interpretován jako číselný posunutí, které chcete buď přidat na základní adresu z registru nebo odebrat. Ale přidejte nebo vezměte závisí na bit U 23.

(Cond) - podmínka provádění operace. Interpretováno stejným způsobem jako pro logické / aritmetické příkazy - čtení nebo záznam může být podmíněno.

Takže v textu assembler můžete napsat:

lDR R1, @ v registru R1 Přečtěte si slovo na adresu z registru R0
LDRB R1, @ v registru R1 Číst bajt na adresu z registru R0
LDREQ R2, @ podmíněné čtení slov
Ldrgtb r2, @ podmíněné čtení
LDR R3, @ čtení slov při 8 vzhledem k adrese z registru R4
LDR R4, @ čtení slov při -16 s ohledem na adresu z registru R5

Kompilace tohoto textu můžete vidět aktuální kódy těchto příkazů:

0: E5901000 LDR R1,
4: E5D01000 LDRB R1,
8: 05912000 LDREQ R2,
C: C5D12000 LDRBGT R2,
10: E5943008 LDR R3,
14: E5154010 LDR R4,

V příkladu výše, používám pouze LDR, ale také se používá str.

Existuje pre-index a režimy pro přístup po indexu s backscapem. V těchto režimech je ukazatel přístupu paměti aktualizován před nebo po provedení příkazu. Pokud jste obeznámeni s programovacím jazykem C, pak znáte návrhy indexů ( * Psource ++; nebo (( a \u003d * ++ Sděcce; ). V procesoru ramene je tento režim přístupu k paměti právě implementován. Při provádění příkazu Read, dvě registry jsou okamžitě aktualizovány - registr přijímače dostane hodnotu čtení a hodnotu v ukazatele registrovat do paměťové buňky se pohybuje vpřed nebo vzad.

Záznam těchto příkazů, podle mého názoru, je poněkud nelogický. Musíte si na vás zvyknout na dlouhou dobu.

lDR R3,! @ PSRC ++; R3 \u003d * PSRC;
LDR R3 ,, 4 @ r3 \u003d * PSRC; PSRC ++;

První příkaz LDR nejprve zvyšuje ukazatel, pak čte čtení. Druhý příkaz nejprve provádí čtení, pak zvyšuje ukazatel. Hodnota ukazatele PSRC je v registru R0.

Všechny výše uvedené příklady byly pro případ, kdy byl resetován bit I 25 v příkazovém kódu. Ale může být stále instalován! Pak v hodnotě ofsetového pole bude numerická konstanta, ale již třetí registr se účastní operace. Navíc hodnota třetího registru může být stále předem posunutá!

Zde jsou příklady možných variací kódu:

0: E7921003 LDR R1, @ Čtení adresy - množství hodnot z registrů R2 a R3
4: E7B21003 LDR R1,! @ Totéž, ale po přečtení R2 bude zvýšeno na hodnotu od R3
8: E6932004 LDR R2 ,, R4 @ první bude čten na R3, a pak R3 se zvýší na R4
C: E7943185 LDR R3, @ Read Adresa R4 + R5 * 8
10: E7B43285 LDR R3,! @ Adresa pro čtení R4 + R5 * 32, po přečtení R4 bude nastaveno na tuto adresu
14: E69431A5 LDR R3, R5, LSR # 3 @ adresa pro čtení R4, po provedení příkazu R4 bude nastaven na R4 + R5 / 8

Jedná se o varianty příkazů čtení / zápisu v procesoru ARM V2A.

Ve starších modelech procesorů ramene je tato řada týmů ještě více.
Důvodem je skutečnost, že procesor umožňuje například číst nejen slova (32bitová čísla) a bajty, ale také poloviční bity (16 bitů, 2 bajty). Pak je přípona "H" přidána do příkazů LDR / STR, ze slova poloviční slovo. Příkazy budou vypadat jako ldh nebo strh. Také načítání příkazů LDRSH nebo LDRSB bajty interpretovatelné jako kultovní čísla. V těchto případech se starší kousek naloženého obvazu nebo bajtových plemen ve starších bitech celého slova v registru přijímače. Například zatížením příkazu LDLSH, 0xFF25 v registru přijímače se získá 0xFFFFFFF25.

Více čtecích a nahrávání.

Příkazy LDR / STR nejsou jedinou pamětí pro přístup k paměti. V procesoru ramene existují stále příkazy, které vám umožní provádět přenos bloků - můžete stáhnout obsah několika po sobě jdoucích slov z paměti bezprostředně několika registrů. Můžete také spálit postupně do paměti hodnoty několika registrů.

MNEMONICS příkazů pro přenos bloků začínají pomocí kořene LDM (Multiple Multiple) nebo STM (ukládat více). Ale dále, jako obvykle v paži, historie začíná přípony.

Obecně vypadá příkaz takto:

op (cond) (režim) rd (, {Register list} !}

Přípona (Cond) je pochopitelná, je to podmínka provedení příkazu. Přípona (režim) je přenosový režim, to je lhat později. RD - Zaregistrujte definování základní adresy v paměti pro čtení nebo psaní. Vykřičník Po registru RD označuje, že po operaci čtení / zápisu se změní. Seznam registrů, které jsou staženy z paměti nebo vyloženy do paměti - to je (seznam registru).

Seznam registrů je nastaven v pořadových závorkách přes čárku nebo ve formě řady. Například:

sTM R0, (R3, R1, R5-R8)

Záznam paměti bude přenesen v pořadí výčtu. Seznam jednoduše označuje, které registry budou zaznamenány v paměti a to je. V kódovém kódu je zde 16 bitů vyhrazeno pro seznam registru, jen podle počtu registrů v procesorové bance. Každý bit v tomto poli označuje, který se registr zúčastní operace.

Nyní o režimu čtení / zápisu. Tam je místo, kde se cítím zmateně. Faktem je, že pro stejnou akci mohou být různé názvy režimů.

Pokud uděláte malou lyrickou odbočku, pak musíte říct o ... zásobníku. Stack je způsob, jak přistupovat k datům jako LIFO - poslední první (wiki) - poslední šel ven, nejprve vyšel. Stack je široce používán v programování při volání postupů a uložení stavu registrů na vstupu funkcí a obnovit je při ukončení, stejně jako při přenosu parametrů nazvaných postupy.

Stack v paměti se stane, kdo by si myslel čtyři typy.

První typ je plný sestupný. To je, když ukazatel zásobníku poukazuje na prvek obsazeného zásobníku a zásobník roste směrem k poklesu adres. Pokud je třeba vložit slovo do zásobníku, pak první indikátor zásobníku klesá (snižování břeče), pak je slovo zaznamenáno v adrese ukazatele zásobníku. Pokud potřebujete odstranit slovo počítače ze zásobníku, je slovo přečteno na aktuální hodnotě ukazatele zásobníku, pak ukazatel se pohybuje nahoru (přírůstek po).

Druhý typ je plný vzestupně. Stoh není roste nahoře, na velké adresy. Ukazatel také označuje zaneprázdněný prvek. Pokud potřebujete vložit slovo do zásobníku, pak nejprve se zvyšuje index zásobníku, pak se záznam slova zaznamenává na znamení. (Přírůstek). Pokud potřebujete odebrat ze zásobníku, nejprve si přečtěte zásobník do zásobníku, protože ukazuje na zaneprázdněný prvek, pak se indikátor zásobníku klesá (snižování AFTE R).

Třetí typ - prázdný sestupně. Stoh roste, jako v případě plného sestupu, ale rozdíl je v tom, že indikátor zásobníku indikuje, že není obsazená buňka. Tak, když potřebujete vložit slovo do zásobníku, pak se nahrávání okamžitě provede, pak indikátor zásobníku klesá (snižování po). Při demontáži ze zásobníku se nejprve zvýšíte ukazatel, pak přečíst (přírůstek).

Čtvrtý typ - prázdný vzestupně. Doufám, že je vše jasné - zásobník vyroste. Ukazatel zásobníku ukazuje na prázdný prvek. Umístěte do zásobníku - zapisujte slovo na adresu ukazatele zásobníku a zvýšit ukazatel zásobníku (přírůstek po). Odstraňte ze zásobníku - snížíte ukazatel zásobníku a přečtěte si slovo (snížená beore).

Při provozu se zásobníkem je tedy nutný ukazatel pro zvýšení nebo snížení - (přírůstek / snížení) před nebo po (před / po) čtení / zápis do paměti v závislosti na typu zásobníku. Například v procesorech Intel jsou například speciální příkazy k práci s push stack (vložte slovo do zásobníku) nebo POP (vyjměte slovo z zásobníku). Neexistují žádné speciální příkazy v procesoru ramene, ale používají se příkazy LDM a STM.

Pokud implementujete zásobník s příkazy procesoru ramene, zobrazí se tento obrázek:

Proč jeden a stejný tým musí dát různá jména? Obecně tomu nerozumím ... tady je samozřejmě třeba poznamenat, že standardu zásobníku pro ruku je stále plná sestupně.

Ukazatel zásobníku v procesoru ramene je registr SP nebo R13. To je obecně taková dohoda. Samozřejmě, StM nahrávání nebo čtení LDM může být provedeno s dalšími základními registry. Je však třeba zapamatovat si, než se registr SP se liší od jiných registrů - to může být vaše vlastní registry v různých režimech provozu procesoru (USR, SVC, IRQ, FIRQ).

A další poznámku. Napište v řádku ARM CODE CODE stiskněte (R0-R3)Určitě můžete. Pouze zde bude stejným týmem. sTMFD SP!, (R0-R3).

Pro poslední, uvádím příklad kódu assembleru a jeho zkompilovanou demontážní text. My máme:


STMFD SP!, (R0-R3)
STMDB SP!, (R0-R3)
Stiskněte (R0-R3)

@ Tyto tři pokyny jsou stejné a dělají to samé
POP (R0-R3)
LDMIA SP!, (R0-R3)
LDMFD R13!, (R0-R3)

STMFD R4, (R0-R3, R5, R8)
STMEA R4!, (R0-R3, R7, R9, LR, PC)
LDM R5, (R0, PC)

Dostáváme se po kompilaci:

0: E92D000F tlačte (R0, R1, R2, R3)
4: E92D000F tlačte (R0, R1, R2, R3)
8: E92D000F tlačte (R0, R1, R2, R3)
C: E8BD000F POP (R0, R1, R2, R3)
10: E8BD000F POP (R0, R1, R2, R3)
14: E8BD000F POP (R0, R1, R2, R3)
18: E904012F STMDB R4, (R0, R1, R2, R3, R5, R8)
1C: E8A4C28F STMIA R4!, R0, R1, R2, R3, R7, R9, LR, PC)
20: E8958001 LDM R5, (R0, PC)

Přechody v programech.

Programování není možné bez přechodů. V jakýchkoli programech, cyklické provedení kódu a výzvou postupů, funkcí, existují také podmíněné provádění kódových sekcí.

V procesoru Amber ARM ARM V2A existují pouze dva příkazy: b (od slova větve - větev, přechod) a BL (pobočka s odkazem - přechod k vrácené adrese).

Syntaxe příkazů je velmi jednoduchá:

b (Cond) štítek
bL (Cond)

Je jasné, že jakékoli přechody mohou být podmíněny, to znamená, že mohou být takové, jako jsou ty, které jsou vytvořeny z kořenů "B" a "BL" a přípustné podmínky (Cond), podivná slova:

bEQ, BNE, BCS, BHS, BCC, BLO, BMI, BPL, BVS, BVC, BHI, BS, BS, BGE, BGT, BLE, BAL, B

bLEQ, BLNE, BLCS, BLHS, BLCC, BLO, BLMI, BLPL, BLV, BLVC, BLLS, BLLS, BLGE, BLGT, BLLE, BLL, BL

Odrůda je nápadná, že?

Příkaz přechodu obsahuje 24bitový ofsetový ofset. Adresa přechodu se vypočítá jako součet aktuální hodnoty ukazatele PC a posunuta 2 bity nalevo od počtu ofsetu, interpretována jako významný počet:

Nový PC \u003d PC + ofset * 4

Přechodový rozsah je tedy 32b vpřed nebo vzad.

Zvažte, jaký je přechod se zadní stranou adresy BL. Tento příkaz slouží k volání podprogramů. Zajímavým vlastností tohoto příkazu je, že návratová adresa z postupu při volání postupu není zachována v zásobníku, jako v procesorech Intel, ale v obvyklém registru R14. Poté se vrátíte z postupu, nepotřebujete speciální příkaz RET, stejně jako ve stejných procesorů Intel a můžete jednoduše zkopírovat hodnotu R14 zpět do počítače. Nyní je jasné, proč registr R14 má alternativní název LR (odkaz odkaz).

Zvažte postup outbyte z projektu Hello-World pro systém na jantarovém krystalu.

000004A0.<_outbyte>:
4A0: E59F1454 LDR R1 ,; 8FC.< адрес регистра данных UART >
4A4: E59F3454 LDR R3 ,; 900.< адрес регистра статуса UART >
4A8: E5932000 LDR R2 ,; Přečtěte si aktuální stav
4AC: E2022020 a R2, R2, # 32
4B0: E3520000 CMP R2, # 0; Zkontrolujeme, že Uart není zaneprázdněn
4B4: 05C10000 StrBEQ R0 ,; Napište symbol v UART pouze v případě, že není zaneprázdněn
4B8: 01B0F00E MOVSEQ PC, LR; Podmíněný návrat z postupu, pokud UART nebyl zaneprázdněn
4BC: 1AFFFFF9 BNE 4A8<_outbyte+0x8> ; Zkontrolujte stav UART

Myslím, že z připomínek tohoto fragmentu je jasné, jak tento postup funguje.

Další důležitou poznámku pro přechody. Registr R15 (PC) může být použit v konvenčních aritmetických nebo logických operacích jako registr přijímače. Takže tým jako Přidat PC, PC, # 8 je docela uživatelská příručka pro přechod na jinou adresu.

Pokud jde o přechody, které potřebujete k další poznámku. Ve starších procesorech má rameno ještě další příkazy pro přechody BX, BLX a BLJ. Jedná se o příkazy pro přechody na fragmenty kódu s jiným příkazovým systémem. BX / BLX umožňuje provádět přechod na rameno pro procesor procesoru týmu 16bitového kódu. BLJ je volání procedury příkazového systému Jazelle (JAVA Language Support v procesorech ramene). Neexistují žádné tyto příkazy v našich jantarových ramenech v2a.

Ostatní pokyny pro procesor ramene.