Asamblator de comandă de braț. Sistemul de instrucțiuni Vivchenniya al procesorului ARM

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
Nu toate depozitele ARM, altfel se vor pierde în rețeaua de trei procesoare, nu introduceți acest articol.
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
Variabilele numerice sunt exprimate după cum urmează:
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.

GBA ASM - Ziua 2: Nu prea multe informații despre asamblatorul ARM - Arhive WASM.RU

ARM este o companie care folosește procesorul GBA. Procesoare ARM și procesoare RISC (în plus față de procesoarele INTEL). RISC înseamnă Reduced Instruction Set Computers (CISC – Complex...). Deși aceste procesoare nu au atât de multe instrucțiuni (ceea ce este bine), instrucțiunile ARM (și poate și alte procesoare RISC, nu știu) pot avea o mulțime de scopuri și combinații diferite care fac procesoarele RISC la fel de puternice pe cât pot fi є .

Registru

Nu știu despre alte procesoare ARM, dar cel care este vicorizat în GBA are 16 registre și este administrat împotriva procesoarelor Intel (și altele), toate registrele pot fi vicorizate ușor (de regulă). Registrele sunt:

r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r13,r14,r15

Wow! Bogat! Lasă-mă să explic în ordine.

ro: Rob ce vrei!

r2 la r12: la fel

r13: Pe sistemele ARM obișnuite, r13 este o cantitate mică pe stivă (SP pe procesoarele INTEL). Nu sunt sigur că r13 joacă același rol în GBA, pot avansa doar ca să fii atent cu el când folosești stiva.

r14: Setați adresa de turnaround pentru procedurile care sunt apelate. Atâta timp cât nu le vikorizezi, poți face ce vrei cu ele.

r15: Program Counter și warrants, precum și IP (Instruction Pointer în Intel). Registrul Intel IP este modificat astfel încât să aveți acces liber la acesta, precum și la orice alt registru, cu excepția cazului în care faceți o modificare înainte ca controlul să fie transferat către alt cod, și schimbați insignele.

Să încercăm puțină matematică la dreapta... 16 minus 3 (numiți-l) ne oferă 13 registre. Chi nu este așa, e cool? Calma.

Acum puteți întreba ce este cu adevărat registrul. Registrele sunt secțiuni speciale de memorie, care fac parte din procesor și nu au adrese active, ci sunt cunoscute doar după numele lor. Înregistrați 32 de biți. Chiar dacă totul se află în ansamblul registrului vikory, este responsabilitatea dumneavoastră să-i cunoașteți la fel ca și rudele.

Instrucțiuni de asamblare ARM

În primul rând, vreau să plec de la faptul că gândul meu este că cel care a dat seama de asamblatorul ARM este un geniu.

Într-un mod diferit, vreau să-l recunosc pe bunul meu prieten CMP. Salută-l și poate, doar poate, va deveni prietenul tău. CMP înseamnă CoMPare. Această instrucțiune poate ajusta registrul și numărul, registrul și registrul sau volumul registrului și memoriei. Apoi, după aliniere, CMP setează steaguri de stare pentru a vă anunța cu privire la rezultatul alinierii. După cum puteți ghici, înregistrarea r15 este pentru răzbunare. Duhoarea informează despre rezultatul curățării. Instrucțiunea CMP a fost creată special pentru a seta semnificația acestor parametri și nu numai.

Prapors se poate răzbuna pe următoarele:

    EQ Equal / Rivne

    NE Nu este egal

    VS oOverflow Set / Instalarea overflow

    VC oOoverflow Clear

    HIgher / Vishche

    LS Mai jos sau la fel / Jos sau la fel

    PL PLUS / Plus

    MI MINus / Minus

    Set de transport CS / Instalare de transport

    CC Carry Clear

    GE Mai mare sau egal

    GT Mai mare decât / Mai mult

    LE Mai puțin de sau Egal / Mai puțin de unu

    LT Less Than / Menshe

    Z este zero

    NZ nu este zero / nu este zero

Acestea joacă un rol important în limbajul de asamblare ARM.

NOTĂ: steaguri nu le salvează mințile (Rivne, Menshe Toscho). Nimic nu contează mai mult decât duhoarea.

Sufixe ale minții

Ați folosit deja instrucțiunea B (Branch). Instrucțiuni B pentru a efectua ceea ce se numește o tranziție nebună (cum ar fi GoTo în Basic sau JMP în asamblarea INTEL). Alternativ, puteți folosi sufixul (unul dintre lucrurile supra-corectate), apoi puteți verifica dacă corespunde taberei însemnului. Cu toate acestea, instrucțiunile de tranziție pur și simplu nu urmează. Dacă doriți să verificați că registrul r0 este relativ la registrul r4 și apoi să mergeți la eticheta numită label34, atunci trebuie să scrieți următorul cod:

    CMP r0, r4; Comentariile din assembler merg după punctele cu comă (;)

    eticheta BEQ34; B este o instrucțiune de tranziție, iar EQ este un sufix, ceea ce înseamnă

    ; "Yakscho Rivno"

NOTĂ: Cu Goldroad Assembler, marcajele nu trebuie să fie potrivite (și în afară de numele mărcii, nu este nimic în neregulă cu rândul.

NOTA II: Scrieți CMP și BEQ mari scriitori Nu este complicat, este doar pentru a te face mai înțelept.

Acum știi cum să lucrezi în poziția de ensign, dar ceea ce nu știi este că poți lucra în poziția de ensign tot ce este posibil, doar da orice instrucțiuni în viitorul sufix bny!

De asemenea, nu trebuie să utilizați CMP pentru a instala ensigns. Dacă doriți, de exemplu, ca instrucțiunea SUB (Scădere) să seteze steaguri, adăugați sufixul „S” la instrucțiune (subsemnează „Set flags”). Acest lucru este interesant, dacă nu doriți să setați starea ensign cu propria instrucțiune CMP, atunci puteți face acest lucru și faceți o tranziție dacă rezultatul este egal cu zero, puteți utiliza următoarea metodă:

    SUBS r0, r1, 0x0FF; Instalez însemnele în consecință cu rezultatul Viconnia

    ; instrucțiuni

    ldrZ r0, = 0x0FFFF; Adăugați în registru r0 0x0FFFF numai în acest caz

    steaguri și zero.

Uită-te in jur

Astăzi am aflat (un pic mai mult) despre registru. Am aflat și despre flexibilitatea instrucțiunilor ARM, care pot fi modificate (sau nu) în timp util. Am învățat multe astăzi.

Mâine vom adăuga cunoștințele de astăzi despre asamblatorul ARM pentru a afișa o imagine pe ecranul GBA.

Ceea ce este imposibil rămâne așa până la ora când devine posibil / Jean-Luc Picard, Capt. ,USS Enterprise/. Mike H, Prov. Acvila

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:

  1. Nume_secțiune- Eu sunt sectia.
  2. 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.
  3. 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 -
  • cu increment înainte
  • LDM (cond) IB Rd (, !} {^}
  • cu creşterea ce urmează
  • LDM (cond) IA Rd (, !} {^}
  • cu decrement anterior
  • LDM (cond) DB Rd (, !} {^}
  • odată cu decrementul care vine
  • LDM (cond)DA Rd(, !} {^}
  • operarea stivei
  • LDM (cond.) Rd(, !}
  • operarea stivei și actualizarea CPSR
  • LDM (cond.) Rd(, !} ^
    operare pe stiva cu registre koristuvach LDM (cond.) Rd(, !} ^
    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 -
  • cu increment înainte
  • STM (cond) IB Rd (, !} {^}
  • cu creşterea ce urmează
  • STM (cond) IA Rd (, !} {^}
  • cu decrement anterior
  • STM (cond) DB Rd (, !} {^}
    o cu decrementul care vine STM (cond)DA Rd(, !} {^}
  • operarea stivei
  • STM(cond.) Rd(, !}
  • operare pe stiva cu registre koristuvach
  • STM(cond.) Rd(, !} ^
    schimb valutar scurgere SWP (cond) Rd, Rm,
    octet SWP (cond) B Rd, Rm,
    Spivprocessor Operație pe date CDP(cond)p , , CRd, CRn, CRm,
    Transferați în registrul ARM de la procesor MRC(cond)p , , Rd, CRn, CRm,
    Transferat la procesor din registrul ARM MCR(cond)p , , Rd, CRn, CRm,
    Citind LDC(cond)p ,CRd,
    Record STC(cond)p ,CRd,
    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
  • C=1, Z=0
  • eticheta BHI
  • C=0, Z=1
  • Eticheta BLS
  • N=1, V=1 sau N=0, V=0
  • Eticheta BGE
  • N=1, V=0 sau N=0, V=1
  • Eticheta BLT
  • Z=0 i ((N sau V=1) sau (N sau V=0))
  • Eticheta BGT
  • Z=1 sau ((N=1 sau V=0) sau (N=0 sau V=1))
  • 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ă -
  • pentru adresa de la ml. registre
  • BX Rs
  • în spatele adresei st. registre
  • BX Hs
    Citind cu constantă -
  • cuvinte
  • LDR Rd,
  • cuvinte
  • LDRH Rd,
  • octeți
  • LDRB Rd,
    cu registru de deplasare -
  • cuvinte
  • LDR Rd,
  • cuvinte
  • LDRH Rd,
  • frază iconică
  • LDRSH Rd,
    LDRB Rd,
  • octet semnat
  • Strada LDRSB,
    Cum se utilizează programul pentru PC LDR Rd,
    Arată stiva SP LDR Rd,
    Adrese -
  • pentru ajutor PC
  • ADD Rd, PC, #10bit_Offset
  • pentru ajutor SP
  • ADD Rd, SP, #10bit_Offset
    Citiri multiple LDMIA Rb!,
    Record cu constantă -
  • cuvinte
  • STR Rd,
  • cuvinte
  • Strada STRH,
  • octeți
  • Strada STRB,
    cu registru de deplasare -
  • cuvinte
  • STR Rd,
  • cuvinte
  • Strada STRH,
  • octeți
  • 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

     

     

    Tse tsikavo: