Asamblator de comandă de braț. Sistemul de instrucțiuni Vivchenniya al procesorului ARM
Bună ziua tuturor!
Meseria mea este ca programator Java. Ultimele luni de muncă m-au împiedicat să învăț cum să folosesc Android NDK și așa mai departe. suplimente nativeîn C. Aici m-am lovit de problema optimizării bibliotecilor Linux. Mulți oameni nu au arătat absolut nicio optimizare pentru ARM și au favorizat puternic procesorul. Neavând practic niciodată programat în limbaj de asamblare înainte, mi-a fost greu să încep să învăț totul, dar tot am decis să încerc. Acest articol este scris, așa că fii sigur, ca un începător pentru începători. Voi încerca să descriu acele elemente de bază pe care, după ce le-am învățat deja, sunt sigur pe cine să le aleg. În plus, de dragul criticilor constructive din partea profesioniștilor.
introduce
Deci, să ne dăm seama ce este ARM pentru moment. Wikipedia oferă următoarea explicație:Arhitectura ARM (Advanced RISC Machine, Acorn RISC Machine, advanced RISC machine) - o familie de nuclee de microprocesoare pe 32 și 64 de biți, licențiate pentru dezvoltare de către ARM Limited. Compania este angajată în dezvoltarea de nuclee și instrumente pentru acestea (compilatoare, instrumente de îmbunătățire etc.), vânzând arhitecturi licențiate către dezvoltatori terți.
După cum nimeni nu știe, de cele mai multe ori dispozitive mobile, tabletele în sine se bazează pe această arhitectură de procesor. Principalul avantaj al acestei familii este consum redus de energie Acesta este motivul pentru care este adesea folosit în diferite sisteme. Arhitectura a evoluat de-a lungul timpului, iar incepand cu ARMv7 au fost atribuite 3 profiluri: 'A' (aplicatie) - add-ons, 'R' (timp real) - ora, 'M' (microcontroller) - microcontroler. Poți citi istoria dezvoltării acestei tehnologii și alte date importante pe Wikipedia sau accesând-o pe Google pe Internet. ARM acceptă diferite moduri de operare (Thumb și ARM, în plus față de Thumb-2 rămas, care include și ARM nebun și Thumb). Acest articol aruncă o privire mai atentă asupra modului ARM, care are un set de comenzi pe 32 de biți.
Creații ARM procesor de piele din următoarele blocuri:
- 37 de registre (dintre care sunt doar 17 vizibile în timpul dezvoltării)
- Arithmetic Logic Unit (ALU) - conține date aritmetice și logice
- Baril shifter - un dispozitiv pentru mutarea blocurilor de date la un singur număr de biți
- CP15 este un sistem special care controlează procesoarele ARM
- Decodor de instrucțiuni - se ocupă de transformarea instrucțiunilor într-o secvență de micro-operații
Execuția conductei
Procesoarele ARM folosesc o conductă în 3 etape (începând cu implementările ARM8, o conductă în 5 etape). Să aruncăm o privire la un transportor simplu de la capul procesorului ARM7TDMI. Următoarele instrucțiuni pentru piele constau în trei pași:1. Etapa de selecție (F)
În această etapă, instrucțiunile merg de la RAM la transportorul procesorului.
2. Etapa de decodare (D)
Instrucțiunile sunt decodificate și tipul lor este recunoscut.
3. Etapa Viconnaya (E)
Datele merg la ALU și sunt salvate, iar valorile rezultate sunt scrise în registrul de locuri de muncă.
De asemenea, atunci când dezvoltați, trebuie să urmați instrucțiunile pentru selectarea unui număr de cicluri vykonanny, de exemplu, încărcare (LDR) sau stocare. În acest caz, etapa victoriei (E) este împărțită în etape (E1, E2, E3...).
Umovne Vikonannya
unu cele mai importante funcții Asamblator ARM - wiki inteligent. Instrucțiunile pentru piele pot fi modificate mental și pentru care se folosesc sufixe. Când se adaugă un sufix la numele unei instrucțiuni, mai întâi trebuie verificați parametrii. Dacă parametrii nu se potrivesc cu mintea, instrucțiunile nu urmează. Sufix:MI - număr negativ
PL - pozitiv sau zero
AL - anulați instrucțiunile pentru totdeauna
Există mult mai multe sufixe de viconn mental. Citiți alte sufixe și aplicații în documentația oficială: documentația ARM
Și acum a sosit momentul să aruncăm o privire...
Elementele de bază ale sintaxei asamblatorului ARM
Tim, care a lucrat anterior cu assembler, poți sări peste acest punct. Pentru a rezolva acest lucru, voi descrie elementele de bază ale muncii mele. De asemenea, un program skin în limbaj de asamblare constă din instrucțiuni. Instrucțiunile sunt scrise după cum urmează:(etichetă) (instrucțiuni | operanzi) (@ comentariu)
Marcajul este un parametru neobligatoriu. Instrucțiunile sunt literalmente mnemonice ale instrucțiunilor către procesor. Instrucțiunile de bază și instrucțiunile care le însoțesc vor fi discutate mai jos. Operanzi - constante, adrese de registru, adrese RAM. Un comentariu este un parametru non-lingvistic care este inclus în program.
Înregistrați nume
Sunt permise următoarele nume de registry:1.r0-r15
3.v1-v8 (registruri modificabile, de la r4 la r11)
4.sb și SB (registru static, r9)
5.sl și SL (r10)
6.fp și FP (R11)
7.ip și IP (R12)
8.sp și SP (R13)
9.lr și LR (r14)
10.pc și PC (software healer, r15).
Zminni si constant
În ansamblurile ARM, precum și (practic) alte programe pot fi modificate prin schimbarea constantelor. Mirosurile sunt împărțite în următoarele tipuri:- Numerele
- Logic
- Riadkovi
un SETA 100; Valoarea numerică „a” este creată pentru valorile de 100.
Modificări de rând:
improba SETS „literal”; Variabila improbabilă este creată cu valorile „literal”. UVAGA! Valorile modificării nu pot depăși 5120 de caractere.
Variabilele logice au de obicei valori TRUE și FALSE.
Aplicați instrucțiunile de asamblare ARM
Din acest tabel am adunat instrucțiunile de bază care vor fi necesare pentru dezvoltarea ulterioară (în stadiul cel mai de bază:):Pentru a consolida această scurtă serie de instrucțiuni de bază, să scriem câteva aplicații simple, altfel vom avea nevoie de un lanț de instrumente pentru braț. Fac asta în Linux tastând: frank.harvard.edu/~coldwell/toolchain (arm-unknown-linux-gnu toolchain). Instalarea este la fel de simplă ca decojirea perelor, ca orice alt program pe Linux. Versiunea mea (fedora rusă) trebuia doar să instaleze pachete rpm de pe site.
Acum este momentul să scrii cel mai simplu fund. Programul va fi absolut un gunoi, doar o farsă, exact :) Codul axei, pe care vă voi învăța:
start: @ Rând inutil, ceea ce înseamnă începutul programului mov r0, #3 @ Valorile 3 sunt adăugate la registrul r0 mov r1, #2 @ La fel cu registrul r1, doar acum de la valorile 2 se adaugă r2, r1 , r0 @ Se adaugă valorile r0 și r1, rezultatul se scrie în r2 mul r3, r1, r0 @ Înmulțiți valoarea registrului r1 cu valoarea registrului r0, rezultatul se scrie în r3 stop: b stop @ Ordinea de finalizarea programului
Compilăm programul în fișierul .bin:
/usr/arm/bin/arm-unknown-linux-gnu-as -o arm.o arm.s /usr/arm/bin/arm-unknown-linux-gnu-ld -Ttext=0x0 -o arm. elf arm .o /usr/arm/bin/arm-unknown-linux-gnu-objcopy -O binary arm.elf arm.bin
(codul se află în fișierul arm.s, iar lanțul de instrumente în cazul meu se află în directorul /usr/arm/bin/)
Dacă totul a mers bine, veți avea 3 fișiere: arm.s (codul), arm.o, arm.elf, arm.bin (programul care va fi configurat). Pentru a verifica programele robotului, nu este necesar să folosiți un dispozitiv de braț puternic. Este suficient să instalați QEMU. Pentru finisare:
QEMU – program gratuit cu opencrit codul de ieșire pentru emularea hardware-ului diferitelor platforme.Include emulare procesoare Intel x86 și dispozitive video de intrare. Poate suporta 80386, 80486, Pentium, Pentium Pro, AMD64 și alte procesoare x86; PowerPC, ARM, MIPS, SPARC, SPARC64, m68k - foarte des.
Funcționează pe Syllab, FreeBSD, FreeDOS, Linux, Windows 9x, Windows 2000, Mac OS X, QNX, Android etc.
De asemenea, pentru a emula arm veți avea nevoie de qemu-system-arm. Acest pachet este în yum, pentru cei care au Fedora, nu trebuie să vă deranjați și să vă deconectați doar de comanda:
yum instalează qemu-system-arm
Apoi, trebuie să lansați emulatorul ARM, astfel încât să intrați în programul nostru arm.bin. În acest scop, creați fișierul flash.bin, care va fi memoria flash pentru QEMU. Este foarte simplu:
dd if=/dev/zero of=flash.bin bs=4096 count=4096 dd if=arm.bin of=flash.bin bs=4096 conv=notrunc
Acum instalați QEMU cu memoria flash eliminată:
qemu-system-arm -M connex -pflash flash.bin -nographic -serial /dev/null
La ieșire, scoateți acest lucru după cum urmează:
$ qemu-system-arm -M connex -pflash flash.bin -nographic -serial /dev/null
Monitor QEMU 0.15.1 - tastați „help” pentru mai multe informații
(qemu)
Programul nostru arm.bin este suficient de mic pentru a modifica valorile mai multor registre, așa că pentru a verifica corectitudinea lucrării, să ne uităm la aceste registre în sine. Puteți face acest lucru doar cu o comandă simplă: registrele de informații
Ca rezultat, veți descărca toate cele 15 registre ARM, iar valorile unora dintre ele vor fi modificate. Verificați:) Valorile registrelor sunt aceleași cu cele care pot fi găsite după instalarea programelor:
(qemu) registre de informații R00=00000003 R01=00000002 R02=00000005 R03=00000006 R04=00000000 R05=00000000 R06=00000000 R00000000000000000000000000 000 R12=00000000 R13=00000000 R14=00000000 R15=00000010 PSR=400001d3 - Z--A svc32
P.S. În acest articol, am încercat să descriu elementele de bază ale programării în ARM assembler. Sper că ai făcut-o! Pe care ar trebui să-l imprim pentru a continua să mă scufund în acest limbaj și să scriu programe pe el? Odată ce totul a fost clar, am scris despre cei pe care îi descopeream eu însumi. În ceea ce mă privește, vă rog să nu vă porți greșit, pentru că sunt nou în asamblare.
De acum BRAŢ finalizați asamblatorul non-standard (pentru a reînvăța de la x86, MCS51 sau AVR). Dacă vrei doar o organizare simplă și logică, atunci vei înțelege.
Există foarte puțină documentație rusă despre limbajul de asamblare. Mi-ar face placere sa vin la a 2-a postare (poate veti sti mai multe si imi spuneti? Voi fi fericit):
Arhitectura și sistemul de comandă al procesoarelor RISC din familia ARM - http://www.gaw.ru/html.cgi/txt/doc/micros/arm/index.htm
Asamblator Touchable ARM, dintr-o serie de articole GBA ASM, autor Mike H, prov. Aquila - http://wasm.ru/series.php?sid=21.
Restul mesajului m-a ajutat foarte mult, ceața s-a curățat =). Prietene, ce poți face pentru a ajuta - nu este surprinzător, C-compiler Banc de lucru încorporat IAR pentru ARM(Dali doar IAR EW ARM). În dreapta este că pentru o lungă perioadă de timp noi (ca toți compilatorii pe care ne respectăm) am reușit să compilam codul C în cod de asamblare, care, în felul său, este ușor de compilat de către asamblatorul IAR în cod obiect. Deci, este ușor să scrieți o funcție simplă în C, să o compilați în asamblator și veți înțelege imediat ce comenzi de asamblare trebuie executate, cum sunt transmise argumentele și cum sunt returnate rezultatele. Omorâți două păsări dintr-o singură piatră - începeți cu asamblatorul și recuperați imediat informațiile despre cum să integrați codul de asamblare într-un proiect în C. M-am antrenat cu privire la funcția de asistență CRC16 și, ca rezultat, l-am recuperat versiunea completaîn asamblator.
Funcția de ieșire a axei în C (u16 înseamnă unsigned short, u32 - unsigned int, u8 - unsigned char):
// fișier crc16.c
u16 CRC16 (void* databuf, dimensiune u32)
{
u16 tmpWord, crc16, idx;
u8bitCnt;
#define CRC_POLY 0x1021;
Crc16 = 0;
idx=0;
în timp ce (dimensiune!=0)
{
/* depozit xor octet mare crc16 i octet de intrare */
tmpWord = (crc16>>8) ^ (*((((u8*)databuf)+idx));
/* rezultatul este scris pe octetul înalt crc16 */
tmpWord<<= 8;
crc16 = tmpWord + (0x00FF & crc16);
pentru (bitCnt=8;bitCnt!=0;bitCnt--)
{
/* reverificăm cea mai mare descărcare a bateriei CRC */
dacă (crc16 și 0x8000)
{
crc16<<= 1;
crc16 ^= CRC_POLY;
}
altfel
crc16<<= 1;
}
idx++;
mărimea--;
}
returnează crc16;
}
Generarea codului de asamblare pentru IAR EW ARM este și mai simplă. În opțiunile pentru fișierul crc16.c (adăugat la proiect) bifați caseta Ignorați setările moștenite, apoi pe fila Listă bifând 3 casete de selectare - Fișierul de asamblare de ieșire, Includeți sursaі Includeți informații despre cadrul de apel(dacă doriți să păstrați caseta de selectare, separat, nu trebuie să o bifați - generează o grămadă de lucruri inutile CFI-Directive). După compilarea fișierului, folder_proiect \ewp\at91sam7x256_sram\List\crc16.s. Acest fișier poate fi adăugat cu ușurință la proiect, ca un fișier C (se va compila în mod normal).
Desigur, dacă aș alimenta compilatorul C cu o versiune netăiată a codului C, atunci aș vedea o astfel de listă a asamblatorului încât nu aș înțelege nimic. Dar dacă am renunțat la toți operatorii C cu excepția unuia din funcție, a devenit mai inteligent. Apoi am adăugat operatori C, bucată cu bucată, și rezultatul a fost:
; fișierul crc16.s
NUME crc16
CRC PUBLIC16
CRC_POLY EQU 0x1021
SECȚIUNEA `.text`:CODE:NOROOT(2)
BRAŢ
// u16 CRC16 (void* databuf, dimensiune u32)
;R0 - rezultatul rotatiei, CRC16
;R1 - parametru de dimensiune
R2 - parametru databuf (intrare la introducerea R0)
;R3, R12 - registre de timp
CRC16:
IMPINGERE (R3, R12); folosind metoda de bifare pentru a salva R3 și R13
; nu obov'kovo. Ale vyrishiv salvează pentru orice eventualitate
; Wow.
MOVS R2,R0 ;acum R2==databuf
MOV R3, #+0
MOVS R0, R3; crc16 = 0
CRC16_LOOP:
CMP R1, # + 0; Au fost colectați toți octeții (dimensiune = = 0)?
BEQ CRC16_RETURN ;dacă da, atunci ieșiți
LSR R3, R0, # +8; R3 = crc16>>8
LDRB R12, ;R12 = *databuf
EOR R3, R3, R12; R3 = * databuf ^ HIGH (crc16)
LSL R3, R3, #+8; R3<<= 8 (tmpWord <<= 8)
ȘI R0, R0, #+255; crc16 &= 0x00FF
Adăugați R0, R0, R3; crc16 = tmpWord + (0x00FF și crc16)
MOV R12, #+8; bitCnt=8
CRC16_BIT_LOOP:
BEQ CRC16_NEXT_BYTE ;bitCnt == 0?
TST R0,#0x8000 ;În comunicare continuă.
BEQ CRC16_BIT15ZERO ;Verificarea celui mai semnificativ bit din crc16.
LSL R0, R0, # +1; crc16<<= 1
MOV R3, # + (LOW (CRC_POLY)); crc16^ = CRC_POLY
ORR R3, R3, # + (HIGH (CRC_POLY)<< 8) ;
EOR R0, R3, R0;
B CRC16_NEXT_BIT
CRC16_BIT15ZERO:
LSL R0, R0, # +1; crc16<<= 1
CRC16_NEXT_BIT:
SUBS R12, R12, #+1; bitCnt--
B CRC16_BIT_LOOP;
CRC16_NEXT_BYTE:
ADAUGĂ R2,R2,#+1;databuf++
SUBS R1,R1,#+1 ;dimensiune--
B CRC16_LOOP ;buclă prin toți octeții
CRC16_RETURN:
POP (R3, R12); Actualizăm registrul
BX LR ;exit subprograme, R0==crc16
Compilatorul IAR produce cod perfect bun. Nu am apucat deloc să-l optimizez. După ce am aruncat cel mai important registru de timp, pe care compilatorul a vrut să-l folosească (cred că am luat vechiul registru de timp LR, deși R3 și R12 erau suficiente), și, de asemenea, am eliminat câteva comenzi importante, care sunt folosite pentru a verifica medicii și setați mandate (adăugând pur și simplu sufixul S la comenzile necesare) .
Așadar, am creat un nou proiect, am finalizat setările de bază, am creat și conectat un fișier la proiectul pe care vrem să-l scriem într-un program simplu în limbaj de asamblare.
Ce urmeaza? Apoi, puteți scrie un program care utilizează setul de comenzi thumb-2, care este suportat de nucleul Cortex-M3. Lista și descrierile comenzilor acceptate pot fi vizualizate în document sub numele Ghidul general al utilizatorului Cortex-M3(capitol Setul de instrucțiuni Cortex-M3), care poate fi găsită în fila Cărți din managerul de proiect, în Keil uVision 5. Detalii despre comenzile thumb-2 vor fi scrise într-una dintre părțile următoare ale acestui articol, dar deocamdată să vorbim despre programele pentru STM32 la început.
Ca orice alt program în limbaj de asamblare, programul pentru STM32 este format din comenzi și pseudo-comenzi care vor fi traduse direct în codul mașinii, precum și diverse directive care nu sunt traduse în codul mașinii, dar sunt convertite în scopuri de service (programe de layout atribuite constantelor nume simbolice etc.)
De exemplu, o directivă specială vă permite să împărțiți un program în secțiuni separate. ZONĂ. Sintaxa avansată Vaughn: AREA Nume_secțiune (, tip) (, attr) ..., de:
- Nume_secțiune- Eu sunt sectia.
- tip- Tipul secțiunii. Pentru o secțiune care stochează date, trebuie să specificați tipul DATE, iar pentru o secțiune care stochează comenzi, trebuie să specificați tipul COD.
- attr- Atribute suplimentare. De exemplu, atributele readonly și readwrite indică în ce memorie va fi localizată secțiunea, atributul align=0..31 indică modul în care secțiunea trebuie configurată în memorie, atributul noinit este folosit pentru a vedea zonele de memorie care nu sunt consumat Fie inițializați, fie inițializați cu zerouri (dacă acest atribut este selectat, este posibil ca tipul de secțiune să nu fie specificat, deși poate fi specificat doar același lucru pentru aceste secțiuni).
Directivă EQU binecunoscut de toată lumea, este folosit în orice limbaj de asamblare și este folosit pentru atribuirea de nume simbolice diferitelor constante, centre de memorie etc. Aceasta este sintaxa ofensivă: Nume EQU numărși informează compilatorul că toate valorile caracterelor care sunt condensate Nume trebuie să-l înlocuiți cu un număr număr. Să zicem că e ca număr Dacă introduceți adresa casetei de memorie, de acum înainte veți putea căuta nu adresa, ci denumiri simbolice echivalente ( Nume).
Directivă OBȚINE nume de fișier inserează text în program dintr-un fișier cu nume nume de fișier. Acesta este un analog al directivei include în limbajul de asamblare pentru AVR. Poate fi modificat, de exemplu, pentru a adăuga directive pentru atribuirea de nume simbolice la diferite registre în fișierul final. Apoi adăugăm toate numele atribuite fișierului alăturat și apoi, pentru ca programul să poată folosi aceste nume simbolice, includem pur și simplu acest fișier în programul nostru cu directiva GET.
Aparent, pe lângă supraasigurare, există și o grămadă de alte directive, a căror listă completă o găsiți la secțiunea Referință la directive document Ghidul utilizatorului Assemblerului, pe care îl puteți cunoaște în Keil uVision 5 următorul pas: tab Cărți manager de proiect -> Instrumente Ghidul utilizatorului -> Selectarea completă a ghidului utilizatorului -> Ghidul utilizatorului Assemblerului.
Majoritatea comenzilor, pseudo-comenzilor și directivelor din program au următoarea sintaxă:
(etichetă) SYMBOL (expr) (, expr) (, expr) (; comentariu)
(etichetă) - marcaj. Acest lucru este necesar pentru a putea fi determinată adresa comenzii de atac. Eticheta este un element neobligatoriu și este folosită numai dacă este necesar să aflați adresa comenzii (de exemplu, pentru a merge la această comandă). Nu există goluri în fața semnului (trebuie să înceapă din prima poziție a rândului), iar marcajul poate începe doar de la literă.
SYMBOL – comandă, pseudo-comandă sau directivă. Comanda de înlocuire a semnului, totuși, trebuie să intre mai întâi în urechea rândului, deoarece nu există niciun semn în fața acestuia.
(expr) (, expr) (, expr) - operand (registru, constantă ...)
; - Rozdilyuvach. Tot textul din rândul care urmează acestei secțiuni este luat ca comentariu.
Ei bine, acum, spunând asta, cel mai simplu program:
AREA START, CODE, READONLY dcd 0x20000400 dcd Program_start ENTRY Program_start b Program_start END |
AREA START, CODE, READONLY dcd 0x20000400 dcd Program_start ENTRY Program_start b Program_start END
Acest program are o singură secțiune, care se numește START. Această secțiune se află în memoria flash (atâta timp cât este selectat atributul numai citire).
Primii 4 octeți ai acestei secțiuni sunt adresa vârfului stivei (în ieșirea noastră 0x20000400), iar ceilalți 4 octeți sunt adresele punctului de intrare (nucleul codului care este adăugat). Urmează codul în sine. În cea mai simplă aplicație de concatenare, codul constă dintr-o singură comandă: o tranziție nebună la eticheta Program_start, astfel încât aceeași comandă este din nou trimisă.
Deoarece există o singură secțiune în flash, atunci în fișierul scatter pentru programul nostru ca First_Section_Name, va trebui să îi indicați numele (sau START).
În acest moment avem date și comenzi mixte. Adresele din partea de sus a stivei și adresele punctului de intrare (date) sunt scrise folosind directive suplimentare dcd direct din secțiunea de cod. Este posibil să scrii așa, dar nu este foarte frumos. Mai ales că vom descrie întregul tabel de întreruperi și blamări (pentru că vom continua să facem asta mult timp), și nu doar vectorul aruncării. Este mult mai bine să nu aglomerați codul cu date fantastice, ci să plasați tabelul de vectori într-o secțiune separată, sau chiar mai bine, într-un fișier separat. În mod similar, într-o secțiune separată sau un număr de fișiere pot fi plasate și stiva inițializată. Noi, de exemplu, putem găzdui totul în următoarele secțiuni:
AREA STACK, NOINIT, READWITE SPACE 0x400; omite 400 de octeți Stack_top; si pune eticheta AREA RESET, DATA, READONLY dcd Stack_top; adrese de etichetă Stack_top dcd Program_start; etichete de adrese Program_start AREA PROGRAM, COD, READONLY ENTRY ; punctul de intrare (cob de cod) Program_start; Marcați începutul programului b Program_start END
Ei bine, același program în sine (ca înainte nu a irosit o singură bucată de scorțișoară), dar acum arată mult mai bine. În fișierul scatter pentru acest program, trebuie să specificați numele First_Section_Name RESET, astfel încât această secțiune să fie mai întâi eliminată din memoria flash.
Această secțiune descrie setul de instrucțiuni al procesorului ARM7TDMI.
4.1 Scurtă descriere a formatului
Această secțiune conține o scurtă descriere a setului de instrucțiuni ARM și Thumb.
Cheia tabelului de seturi de instrucțiuni este prezentată în Tabelul 1.1.
Procesorul ARM7TDMI se bazează pe arhitectura ARMv4T. O descriere mai detaliată a ambelor seturi de instrucțiuni poate fi găsită în Manualul de referință pentru arhitectura ARM.
Tabelul 1.1. Cheia la masă
Formatul setului de instrucțiuni ARM îl arată pe cel mic 1.5.
Pentru informații mai detaliate despre formatele setului de instrucțiuni ARM, consultați Manualul de referință pentru arhitectură ARM.
Malyunok 1.5. Format set de instrucțiuni ARM
Unele coduri de instrucțiuni nu sunt specificate, dar nu declanșează căutarea instrucțiunilor neimportante, de exemplu, instrucțiunea de înmulțire cu bitul 6 este schimbată la 1. Se recomandă evitarea folosirii unor astfel de instrucțiuni deoarece În viitor, această activitate poate fi modificată. Rezultatul descărcării acestor coduri de instrucțiuni din depozitul procesorului ARM7TDMI nu a fost transferat.
4.2 Scurtă descriere a instrucțiunilor ARM
Setul de instrucțiuni ARM este prezentat în Tabelul 1.2.
Tabelul 1.2. Scurtă descriere a instrucțiunilor ARM
Operațiuni | Sintaxa de asamblare | |
Peresilanya | Peresilanya | MOV (cond)(S) Rd, |
NU copleșit | MVN (cond)(S) Rd, |
|
Transferarea SPSR în registru | MRS (cond) Rd, SPSR | |
Peresilannya CPSR la registru | MRS (cond) Rd, CPSR | |
Transfer în registrul SPSR | MSR (cond) SPSR (câmp), Rm | |
Peresilannya CPSR | MSR (cond) CPSR (câmp), Rm | |
Peresilannya constanti u prapori SPSR | MSR (cond.) SPSR_f, #32bit_Imm | |
Peresilannya constanti u prapori CPSR | MSR (cond) CPSR_f, #32bit_Imm | |
Aritmetic | Dodavannya | ADD (cond) (S) Rd, Rn, |
Adăugat la ceea ce a fost transferat | ADC (cond)(S) Rd, Rn, |
|
Vіdnіmannya | SUB (cond)(S) Rd, Rn, |
|
Ziua amânării | SBC (cond)(S) Rd, Rn, |
|
Ziua Porții | RSB (cond)(S) Rd, Rn, |
|
Ziua de întoarcere așa cum a fost reprogramată | RSC (cond)(S) Rd, Rn, |
|
multiplicare | MUL (cond)(S) Rd, Rm, Rs | |
Înmulțirea și acumularea | MLA (cond)(S) Rd, Rm, Rs, Rn | |
Înmulțirea numerelor lungi nesemnate | UMULL | |
Înmulțire - acumulare nesemnată de valori lungi | UMLAL (cond)(S) RdLo, RdHi, Rm, Rs | |
Înmulțirea reperelor emblematice | SMULL (cond)(S) RdLo, RdHi, Rm, Rs | |
Înmulțirea - o acumulare simbolică de semnificații lungi | SMLAL (cond)(S) RdLo, RdHi, Rm, Rs | |
Porivnyannya | CMP (cond) Rd, |
|
Egalizarea nu este negativă | CMN (cond) Rd, |
|
Logic | Reverificare | TST (cond.) Rn, |
Verificarea echivalenței | TEQ (cond) Rn, |
|
Buturuga. eu | AND (cond)(S) Rd, Rn, |
|
Vikl. ABO | EOR (cond)(S) Rd, Rn, |
|
ORR | ORR (cond)(S) Rd, Rn, |
|
Skidannya bita | BIC (cond)(S) Rd, Rn, |
|
Tranziție | Tranziție | (cond)etichetă |
Trecând dincolo de ordine | (cond)etichetă | |
Tranziția și modificarea unui set de instrucțiuni | (cond)Rn | |
Citind | cuvinte | LDR (cond) Rd, |
LDR(cond)T Rd, |
||
octeți | LDR (cond)B Rd, |
|
LDR (cond)BT Rd, |
||
semnul octet z | LDR (cond) SB Rd, |
|
cuvinte | LDR (cond) H Rd, |
|
cuvinte și semne | LDR(cond)SH Rd, |
|
operațiuni cu mai multe blocuri de date | - | |
LDM (cond) IB Rd (, !} |
||
LDM (cond) IA Rd (, !} |
||
LDM (cond) DB Rd (, !} |
||
LDM (cond)DA Rd(, !} |
||
LDM (cond.) |
||
LDM (cond.) |
||
operare pe stiva cu registre koristuvach | LDM (cond.) |
|
Record | cuvinte | STR (cond) Rd, |
cuvinte în folosul regimului Koristuvac | STR (cond)T Rd, |
|
octeți | STR (cond) B Rd, |
|
octeți la modul koristuvach | STR (cond)BT Rd, |
|
cuvinte | STR (cond) H Rd, |
|
operațiuni pe mai multe blocuri de date | - | |
STM (cond) IB Rd (, !} |
||
STM (cond) IA Rd (, !} |
||
STM (cond) DB Rd (, !} |
||
o cu decrementul care vine | STM (cond)DA Rd(, !} |
|
STM(cond.) |
||
STM(cond.) |
||
schimb valutar | scurgere | SWP (cond) Rd, Rm, |
octet | SWP (cond) B Rd, Rm, | |
Spivprocessor | Operație pe date | CDP(cond)p |
Transferați în registrul ARM de la procesor | MRC(cond)p |
|
Transferat la procesor din registrul ARM | MCR(cond)p |
|
Citind | LDC(cond)p |
|
Record | STC(cond)p |
|
Programare | SWI 24bit_Imm |
Vă puteți familiariza cu sistemul de comandă în modul ARM.
Moduri de adresare
Modurile de adresare sunt proceduri care sunt modificate prin diverse instrucțiuni pentru a crea valori care sunt modificate prin instrucțiuni. Procesorul ARM7TDMI acceptă 5 moduri de adresare:
- Modul 1 – Operanzi esențiali pentru instrucțiunile de prelucrare a datelor.
- Modul 2 - Citiți și scrieți un cuvânt sau un octet fără semn.
- Modul 3 - Citirea și scrierea unui singur cuvânt sau obținerea unui octet de semn.
- Modul 4 - Citire și scriere numerică.
- Modul 5 - Citiți și scrieți procesorul.
Modurile de adresare cu tipuri desemnate și coduri mnemonice sunt prezentate în Tabelul 1.3.
Tabelul 1.3. Moduri de adresare
Modul de adresare | Tip sau modul de adresare | Cod mnemonic sau tip stivă |
Modul 2 |
Constant | |
Registrul de înregistrare | ||
Registrul de scară | ||
Compensații indexate înainte | - | |
Constant | ! | |
Registru | ! | |
Registrul de scară | ! | |
! | ||
! | ||
! | ||
! | ||
- | ||
Constant | , #+/-12bit_Offset | |
Registru | , +/-Rm | |
Registrul de scară | ||
Modul 2, privilegii |
Constant | |
Registrul de înregistrare | ||
Registrul de scară | ||
Înlocuiri cu indexarea curentă | - | |
Constant | , #+/-12bit_Offset | |
Registru | , +/-Rm | |
Registrul de scară | , +/-Rm, LSL #5bit_shift_imm | |
, +/-Rm, LSR #5bit_shift_imm | ||
, +/-Rm, ASR #5bit_shift_imm | ||
, +/-Rm, ROR #5bit_shift_imm | ||
Modul 3, |
Constant | |
! | ||
Se apropie indexarea | , #+/-8bit_Offset | |
Registru | ||
Indexare înainte | ! | |
Se apropie indexarea | , +/-Rm | |
Modul 4, citire |
IA, increment ofensiv | FD, complet descendent |
ED, gol descendent | ||
DA, reducere anticipată | FA, complet ascendent | |
DB decrement anterior | EA, gol ascendent | |
Modul 4, înregistrare |
IA, increment ofensiv | FD, complet descendent |
IB, increment înainte | ED, gol descendent | |
DA, reducere anticipată | FA, complet ascendent | |
DB decrement anterior | EA, gol ascendent | |
Modul 5, transmisie de date CPU |
Constant | |
Indexare înainte | ! | |
Se apropie indexarea | , #+/-(8bit_Offset*4) |
Operandul 2
Un operand este o instrucțiune parțială care este trimisă către un dispozitiv dat sau periferic. Operandul 2 este prezentat în Tabelul 1.4.
Tabelul 1.4. Operandul 2
Câmpurile sunt prezentate în tabelul 1.5.
Tabelul 1.5. Câmpuri
Câmpuri ale minții
Câmpurile minții sunt prezentate în tabelul 1.6.
Tabelul 1.6. Câmpuri ale minții
Tipul câmpului | Sufix | Descriere | Umova |
Umova (cond) | EQ | Rivne | Z=1 |
NE | Nu se compara | Z=0 | |
C.S. | Nesemnat mai mult de unul | C=1 | |
CC | Nesemnat mai puțin | C=0 | |
MI | Negativ | N=1 | |
P.L. | Pozitiv sau zero | N=0 | |
VS | Reînnoit | V=1 | |
V.C. | Nu există înlocuire | V=0 | |
BUNĂ | Mai mult nesemnat | C=1, Z=0 | |
L.S. | Nesemnat mai puțin de unu | C=0, Z=1 | |
GE. | Mai mult sau mai vechi | N=V (N=V=1 sau N=V=0) | |
LT | Mensche | NV (N=1 și V=0) sau (N=0 și V=1) | |
GT | Mai mult | Z=0, N=V (N=V=1 sau N=V=0) | |
L.E. | Mai puțin sau mai vechi | Z=0 sau NV (N=1 și V=0) sau (N=0 sau V=1) | |
AL | Întotdeauna sincer | însemnele sunt ignorate |
4.3 Scurtă descriere a setului de instrucțiuni Thumb
Formatul setului de instrucțiuni Thumb îi arată pe cel mic 1.6. Un raport cu privire la formatele seturilor de instrucțiuni ARM este furnizat de „Manualul de referință arhitectural ARM”.
Malyunok 1.6. Format set de instrucțiuni pentru degetul mare
Setul de instrucțiuni Thumb este prezentat în Tabelul 1.7.
Tabelul 1.7. O scurtă descriere a setului de instrucțiuni Thumb
Operațiune | Sintaxa de asamblare | |
Peresilanya (copie) | constanti | MOV Rd #8bit_Imm |
bătrân spre tânăr | MOV Rd, Hs | |
tineri spre bătrâni | MOV HD, Rs | |
senior la senior | MOV Hd, Hs | |
Aritmetic | adiţional | ADD Rd, Rs, #3bit_Imm |
adaugă tineri la tineri | ADD Rd, Rs, Rn | |
adaugă mai în vârstă la mai tânără | ADD Rd, Hs | |
adaugă pe cel mai tânăr celui mai mare | ADAUGĂ HD, Rs | |
adăuga senior la senior | ADAUGĂ Hd, Hs | |
adaos cu o constantă | ADD Rd #8bit_Imm | |
adăugați valori la SP | ADD SP, #7bit_Imm ADD SP, #-7bit_Imm | |
adăugat la urahuvannyam transferat | ADC Rd, Rs | |
vidnіmannya | SUB Rd, Rs, Rn SUB Rd, Rs #3bit_Imm | |
constantele vydnimannya | SUB Rd #8bit_Imm | |
Reînnoire de la reprogramat | SBC Rd, Rs. | |
Inversarea semnului | NEG Rd, Rs | |
multiplicare | MUL Rd, Rs. | |
echivalează tinerii cu tinerii | CMP Rd, Rs. | |
egalează tot mai tineri și mai în vârstă | CMP Rd, Hs | |
egalizați mai bătrâni și mai tineri | CMP Hd, Rs | |
egalează senior și senior | CMP Hd, Hs | |
egalează negativul | CMN Rd, Rs. | |
egală cu constantă | CMP Rd #8bit_Imm | |
Logic | І | ȘI Rd, Rs |
Vikl. ABO | EOR Rd, Rs | |
ABO | ORR Rd, Rs | |
Skidannya bita | BIC Rd, Rs. | |
NU copleșit | MVN Rd, Rs. | |
Bit de testare | TST Rd, Rs | |
Zsuv/obertannya | Rotire logica spre stanga | LSL Rd, Rs, #5bit_shift_imm LSL Rd, Rs |
Zsuv logic dreptaci | LSR Rd, Rs, #5bit_shift_imm LSR Rd, Rs | |
Aritmetică zsuv dreptaci | ASR Rd, Rs, #5bit_shift_imm ASR Rd, Rs | |
Înfășurați dreapta | ROR Rd, Rs | |
Tranziție | tranziții mentale | - |
Eticheta BEQ | ||
Eticheta BNE | ||
Eticheta BCS | ||
eticheta BCC | ||
Eticheta IMC | ||
Eticheta BPL | ||
Eticheta BVS | ||
Eticheta BVC | ||
eticheta BHI | ||
Eticheta BLS | ||
Eticheta BGE | ||
Eticheta BLT | ||
Eticheta BGT | ||
eticheta BLE | ||
Tranziție nebună | eticheta B | |
Călătorie lungă pentru a ajunge la destinație | Eticheta BL | |
Va exista o modificare opțională | - | |
BX Rs | ||
BX Hs | ||
Citind | cu constantă | - |
LDR Rd, | ||
LDRH Rd, | ||
LDRB Rd, | ||
cu registru de deplasare | - | |
LDR Rd, | ||
LDRH Rd, | ||
LDRSH Rd, | ||
LDRB Rd, | ||
Strada LDRSB, | ||
Cum se utilizează programul pentru PC | LDR Rd, | |
Arată stiva SP | LDR Rd, | |
Adrese | - | |
ADD Rd, PC, #10bit_Offset | ||
ADD Rd, SP, #10bit_Offset | ||
Citiri multiple | LDMIA Rb!, |
|
Record | cu constantă | - |
STR Rd, | ||
Strada STRH, | ||
Strada STRB, | ||
cu registru de deplasare | - | |
STR Rd, | ||
Strada STRH, | ||
Strada STRB, | ||
shodo SP | STR Rd, | |
Multi-înregistrare | STMIA Rb!, |
|
Amplasare/sertar din stivă | Puneți registrele pe stivă | APĂSAŢI |
Așezați LR și registrele pe stivă | APĂSAŢI |
|
Desenați registre din stivă | POP |
|
Conectați-vă la registrul PC-ului din stivă | POP |
|
Programare | - | SWI 8bit_Imm |