Documente Academic
Documente Profesional
Documente Cultură
Departamentul Microelectronica și
Inginerie Biomedicală
Microprocesoare și Interfețe
CUPRINS
4.1. Inițiere în ASM.
4.2. Stiva
4.3. Subrutina
4.3.1. MACRO
4.4. Realizarea construcţiilor algoritmice de bază
4.5. Constante
4.6. Logica booleană
4.1. Inițiere în ASM
Diferența principală între RJMP și JMP prezintă numărul de tacturi necesare pentru
efectuarea instrucției.
4.1. Inițiere în ASM
Testarea în ASM:
Diferența principală între RJMP și JMP prezintă numărul de tacturi necesare pentru
efectuarea instrucției.
.CSEG ; Кодовый сегмент
M1: NOP
NOP
LDI ZL,low(M2) ; Загрузили в индекс
LDI ZH,High(M2)
LDI R16, 55
;LDI R1, 20
IJMP
NOP
NOP
NOP
M2: NOP
RJMP M1
NOP
Команда LDI загружает непосредственное значение в регистр старшей (от R16
до R31) группы.
R0 .. R15 - nu sunt disponibili pentru operaţiile cu constante!
4.1. Inițiere în ASM
Testarea în ASM:
NOP
NOP
NOP
M2: NOP
RJMP M1
NOP
Instrucțiunea IJMP face saltul la adresa din perechea registrilor Z (în care am inclus
adres etichetei M2).
4.1. Inițiere în ASM
Directiva .org
; FLASH ===================================================
.CSEG ; Кодовый сегмент
NOP
.ORG 0x0010
M1: NOP
NOP
LDI ZL,low(M2) ; Загрузили в индекс
LDI ZH,High(M2)
IJMP
NOP
NOP
NOP
M2: NOP
RJMP M1
NOP
; FLASH ====================================================================
.CSEG; Кодовый сегмент
NOP
.ORG 0x0010
M1: NOP
LDI ZL,low(M2); Загрузили в индекс
LDI ZH,High(M2)
LDI contor, 100
LDI buffer, 200
IJMP
M2: NOP
RJMP M1
NOP
;===========================================================================
4.1. Inițiere în ASM
Lucrul cu registrii I/O
Ca exemplu analizăm un registru I/O periferic UDR (la moment nu are importanță care
anume și ce rol are), care are adresa 0x0C (0х2С – adresa lungă)
Instrucțiunele IN/OUT sunt cu 1 tact mai scurte deoarece lucrează cu adrese mai scurte
decât LOAD/STORE.
4.1. Inițiere în ASM
Lucrul cu registrii I/O
.cseg
SBI SREG,0
SBI SREG, 7
CLC
SEC
SBI și CBI lucrează doar pentru registrii I/O cu adresa de până la 0x3F
Deasemenea stiva este un mecanism fara de care nu este posibil lucrul cu subrutinele, deoarece
mecanismul stivei permite stocarea temporara a Contorului de Program PC pe durata executiei
subrutinei. Respectiv comenzile de tip CALL si RET deasemenea vor introduce/extrage date din
stiva.
Mecanismul de stiva este realizat in baza memoriei RAM si un Registru Indicator de Stiva - SP
(Stack Pointer).
Indicatorul de stiva SP indica la adresa curenta de scriere in spatiul RAM.
SP este un registru dublu (16 biti), construit in baza [ SPH : SPL ] facilitand accesul la intreg
spatiul de memorie, pana la 64 K.
4.2. Stiva (Stack)
RAM
4.2. Stiva (Stack)
Executand comanda PUSH R continutul registrului se va inregistra la adresa ce se
contine in registrul Indicator de Stiva SP, dupa care are loc decrementarea SP.
PUSH R
1. RAM[SP] = R
2. SP = SP - 1
POP R
1. SP = SP + 1
2. R = RAM[SP]
Adaugarea elementelor in stiva va implica cresterea stivei. reesind din cele spuse mai
sus, vom afirma ca Stiva creste in directia diminuarii adreseilor memoriei RAM.
4.2. Stiva (Stack)
Initializarea Stivei
Secventa de cod in ASM pentru operatia de mai sus va arata in felul urmator:
unde:
• LOW - macroinstructiunea pentru selectarea byte-ului inferior dintr-o constanta.
• HIGH - macroinstructiunea pentru selectarea byte-ului superior dintr-o constanta.
LDI R16,High(RAMEND)
OUT SPH,R16
Subrutina poate fi apelata prin numele ei cu una din comanzile de chemare subrutinei
CALL, RCALL sau ICALL.
...
rcall MySub ; apelul subrutinei MySub
...
4.3. Subrutina
Mecanismul de chemare a subrutinei consta in salvarea adresei
curente de executie in stiva pentru a avea posibilitatea de a
restabili executia comenzilor urmatoare dupa returnarea din
subrutina.
Instructiunea de apel a subrutinei cu o instructiune de til CALL
va fi interpretata dupa cum urmeaza:
• PC -> STACK - salvarea adresei curente in Stiva
• jmp MySub - salt la adresa etichetei My Sub
Pentru returnare din subrutina vom avea:
• PC <- STACK - restabilirea adresei din stiva
• PC <- PC + 1 - trecerea la comanda urmatoare dupa
comanda de apel a subrutinei
4.3. Subrutina
De mentionat ca Contorul de Program PC este un registru de 16 biti, respectiv va a ocupa
doua locatii in stiva, executandu-se doua operatii de salvare a unui byte in stiva.
Deoarece un apel de subrutina presupune utilizarea stivei, este strict recomandat ca
inainte de un oarecare prim apel stiva sa fie initializata, iar locul cel mai potrivit este in
partea de initializare a programului.
In calitate de parametri al unei subrutine pot fi utilizati registrii de uz general. In asa mod
pentru a transmite date de intrare in subrutina, inainte de a apela o subrutina este nevoie
ca registrii utilizati ca parametri sa fie initializati cu valorile de intrare dorite pentru acesti
parametri. Iar dupa executia subrutinei se vor prelua valorile din registrii rezervati
parametrilor de iesire.
De exemplu daca vom avea o subrutina care va utiliza R16 si R17 ca parametri de
intrare si R18 ca parametru de iesire, in care subrutina va stoca rezultatul și de exemplu
vom avea de evaluat o expresie de tipul:
a = MySub(K1, K2)
...
...
push r16 ; salvarea registrului parametru r16
push r17 ; salvarea registrului parametru r17
push r18 ; salvarea registrului parametru r18
ldi r16, K1 ; initializarea primului paramatru
ldi r17, K1 ; initializarea parametrului al doilea
rcall MySub ; apelul subrutinei MySub
sts a, r18 ; preluarea rezultatului subrutinei
pop r18 ; restabilirea registrului parametru r16
pop r17 ; restabilirea registrului parametru r17
pop r16 ; restabilirea registrului parametru r18
...
...
4.3.1. MACRO
SUBI16 0x1234,r16,r17
Introducerea
sau afișare (I/O)
Verificarea unor
condiții
Calcule
Pentru executarea necondiționată vom avea asa numiții algoritmi seriali, care
sunt compuși dintr-o serie de operații de transfer și prelucrare.
4.4. Realizarea construcţiilor algoritmice de bază
Execuția condiționată presupune execuția unui set de instrucțiuni de transfer sau
prelucrare în dependența de o condiție.
Comenzile de acest tip sunt comenzi care după testarea unei anumite condiții,
presupuse de comanda, de obicei fiind un bit din registrul de stare SREG, execută
un salt a execuției la o adresa fixă specificată de eticheta (label). În constext vom
numi acest tip de comenzi ca BR_OP - operații de ramificare. Biții verificați din
SREG pot fi gasiți în tabelul de comenzi a operațiilor de transfer al controlului,
operații de salt condiționat.
4.4. Realizarea construcţiilor algoritmice de bază
Implementarea algoritmilor cu comenzi de salt condiționat
O comanda de tip BR_OP de cele mai dese ori este precedată de o instrucțiune
de comparație CP, CPI sau TEST. Comenzile de comparație sunt menite pentru
a evalua relația între elementele participante la TEST având ca rezultat
modificarea registrului de stare SREG. O instrucțiune de tip BR_OP poate să nu
fie precedată de o operație comparație. Acest lucru este posibil în cazul în care
operația de prelucrare de înaintea operației de ramificare configurează corect
registrul SREG în starea dorită pentru ramificare. De exemplu după o
decrementare până la ZERO în cicluri. De fapt în spatele comparației se execută
o operație de scădere fără a salva rezultatul operației, iar ca urmare a operației
de scădere se vor seta biții din registrul de stare SREG.
4.4. Realizarea construcţiilor algoritmice de bază
Implementarea algoritmilor cu comenzi de salt condiționat
NoAction: NOP
Iar definiția comenzii va suna în felul următor: Salt peste o comandă (PC =
PC+2) dacă bitul N din registrul TST_REG este setat/resetat. În caz contrar
execută comanda următoare (PC=PC+1).
4.4. Realizarea construcţiilor algoritmice de bază
Implementarea ramificărilor cu comenzi de ignorare a următoarei comenzi.
SBIS – skip (S) if bit (B) in I/O Register (I) is set (S)
SBIC – skip (S) if bit (B) in I/O Register (I) is clear (S)
În SBI* se include și registrul SREG, care la fel este un registru I/O
Instrucțiunele SBI* pot verifica registrii I/O cu adresa inclusă între 0x00 și 0x1F (pentru
ATmega16A), pentru alte modele a se verifica datasheet.
Ceilalți registri I/O se vor verifica cu măști!
4.4. Realizarea construcţiilor algoritmice de bază
Vom realiza mai jos construcția
algoritmică de ramificare
și implementarea ei în ulimbajul
ASM unde etichetele L1, L2, L3 și L4
corespund punctelor cu același nume.
4.4. Realizarea construcţiilor algoritmice de bază
Implementarea ramificărilor cu comenzi de ignorare a următoarei comenzi.
L1: ; inceputul constructiei de ramificare
SB_OP ; operatia ignorare a comenzii ce urmeaza
rjmp L3 ; salt la executia clauzei FALSE
(rjmp L2) ; salt la executia clauzei TRUE, poate fi omis
L2: ; T - test TRUE
...
... ; OP1 - setul de instructiuni pentru ramura
TRUE
...
rjmp L4 ; salt neconditionat la sfarsitul
; constructiei de ramificare
L3: ; F - test FALSE
...
... ; OP2 - setul de instructiuni pentru ramura
FALSE
...
(rjmp L4) ; poate fi omis
L4: ; sfarsitul constructiei de ramificare
4.4. Realizarea construcţiilor algoritmice de bază
Realizarea construcțiilor algoritmice complexe în baza ramificărilor
După cum s-a putut observa construcțiile algoritmice discutate pana acum se
refera in special implementării instructiunii if ... else a limbajelor de nivel
înalt (cum ar fi C/C++).
Majoritatea limbajelor de nivel inalt au un set de instrucțiuni specializate pentru
implementarea construcțiilor algoritmice condiționale, selecție, și ciclice cum ar fi:
• Condiționale
if ... else if
switch/case
• Cicluri
while
do ... while
for
Vom analiza fiecare construcție în parte și von da o realizare în limbajul ASM a
fiecărei din acestea.
4.4. Realizarea construcţiilor algoritmice de bază
Imlementarea instructiunilor if ... else if
if(R16==15) R17++
else if (R16>20) R17—
else if (R16<10) R17 = 0
else R17 = 255
4.4. Realizarea construcţiilor algoritmice de bază
Imlementarea instructiunilor (if else)
if (А>=B){ action_a }
else { action_b }
if (А>B){ action_a }
else { action_b }
; R16 = A, R17 = B
CP R16,R17 ; Сравниваем два значения
BREQ action_b ; Если равно (флаг Z), то переход сразу.
; Потом проверяем второе условие.
BRCS action_b ; когда A>B флага С не будет
; Перехода не произойдет
next_action: NOP
4.4. Realizarea construcţiilor algoritmice de bază
Imlementarea instructiunilor (if else)
if (C<A AND A<B){ action_a }
else { action_b }
; R16 = A, R17 = B, R18 = C
;IF
CP R16,R18 ; Сравниваем С и А
BREQ action_b ; Переход сразу на ELSE если С=А
BRCS action_b ; Если А оказалось меньше, то будет С
; и сразу выходим отсюда на else
; Но если C<A то идем дальше и проверяем
; Второе условие (A<B)
next_action: NOP
4.4. Realizarea construcţiilor algoritmice de bază
Instrucțiunea de selectie switch/case
Această instrucțiune permite execuția unei secvențe de cod atîta timp cât o
condiție este adevărată. Adică mai întâi se evaluează condiția și în cazul când
condiția este satisfacută se execută un set de instrucțiuni după care are loc un
salt spre o nouă comparație formând o buclă de execuție. În cazul în care condiția
dă un rezultat FALSE instrucțiunile incluse în secvența ciclului nu se mai execuă
și are loc un salt necondiționat la prima instrucțiune după ciclu. Construcția
algoritmică pentru un asemenea ciclu va arăta în felul urmator:
4.4. Realizarea construcţiilor algoritmice de bază
Instructiune de ciclu cu pre comparare while
4.4. Realizarea construcţiilor algoritmice de bază
Instrucțiune de ciclu cu post comparare do ... while
Pentru această construcție algoritmică vom avea mai întîi execuția setului de
instrucțiuni cuprinse în ciclu după care se va evalua comparația. În cazul când
condiția se satisface vom avea un salt spre începutul blocului de instrucțiuni. În
cazul în care nu se satisface condiția execuția continuă cu urmatoarea comandă
după cea de comparație. Am putea organiza instrucțiunile în așa mod ca ultima
instrucțiune din setul cuprins în corpul ciclului să seteze flagurile din SREG
pentru a fi evaluate de către instrucțiunea de comparație BR_OP, și respectiv
vom putea exclude din ciclu operația de comparație CP.
4.4. Realizarea construcţiilor algoritmice de bază
Instructiune de ciclu for
De aici incolo temp poate fi utilizat ca operand în locul registrului R16, și orice modificre
a lui temp va fi de fapt o modificare a lui R16.
Exemple:
Exemplu:
DEC | BIN | HEX După cum vedem fiecărei tedrade binare i se asociază o
0 | 0000 | 0 cifră în hexazacimal. În așa mod un număr pe 16 biți va fi
1 | 0001 | 1 reprezentat de 2 octeți (8bit) adică 4 tetrade respectiv
2 | 0010 | 2 poate fi reprezentat de 4 cifre hexazecimale.
3 | 0011 | 3
4 | 0100 | 4 Exemplu:
5 | 0101 | 5
6 | 0110 | 6
7 | 0111 | 7 Această conversie se poate efectua ușor dintr-o bază în
8 | 1000 | 8 alta, iar exersând se poate ajunge la un automatizm într-
9 | 1001 | 9 un timp scurt.
10 | 1010 | A
11 | 1011 | B 0xFF = 1111 1111 = 255
12 | 1100 | C 0xA1 = 1010 0001 =
13 | 1101 | D
14 | 1110 | E
15 | 1111 | F
4.5. Constante
Moduri de reprezentare a numerelor constante si conversii
x OR 0 = x - nu modifica valoarea x
x OR 1 = 1 - seteaza in 1
Făcând aceeași analiză a operațiilor logice pentru a găsi o soluție pentru a reseta
locațiile respective vom observa că:
x AND 0 = 0 - reseteaza in 0
x AND 1 = x - nu modifica valoarea x
Masca de resetare vom numi o combinație de biți în care vom avea zerouri în
pozițiile pe care vrem să le resetăm. Operația de resetare va fi realizată în baza
operației AND a numărului cu masca.
4.6. Logica booleană
Inversarea cu masca.
Pentru a inversa anumiți biți dintr-un număr vom aplica operatia XOR cu masca în
care pozițiile de interes pentru inversare vor fi setate cu 1 iar celelalte respectiv cu
zero. Ceia ce rezultă din urmatoarele.
Pentru cazul în care vom avea format o mască cu mai mulți biți de interes, de ex
4,6,7, vom defini o expresie constantă în baza sumei măștilor pentru fiecare bit de
interes, adică:
.EQU MASK = (1<<7)+(1<<6)+(1<<4)
4.6. Logica booleană
Formarea măștilor
Același rezultat il vom avea dacă vom evalua exresia prin funcția OR al
componentelor ce formează masca:
Lucrul cu măștile este utilizat de obicei la setarea sau resetarea unor biți dintr-un
registru periferic. Fiecare bit în acest caz are un nume definit în fișierul antet
pentru fiecare microcontroller în parte, sau am putea defini un nume în cadrul
programului pentru acești biți, după care să utilizăm numele bitului pentru
formarea măștilor:
.EQU BITA = 7
.EQU BITB = 4
.EQU MASK = (1<<BITA)(1<<BITB)
Pasul 2. Inversarea biților dintr-un registru aleatoriu Rx cu valoarea 1111 1111 (0xFF)
/* stocarea valorii măștii in registrul Ry */
/* Cauza stocării în registru constă în faptul ca instrucțiunea EOR nu poate fi aplicată
între un registru si o constantă */
Ldi Ry, MASK
/* Inversarea biților din registrul Rx */
EOR Rx, Ry
Pasul 2. Setarea biților dintr-un registru aleatoriu Rx cu valoarea 0000 0000 (0x00)
/* Setarea biților din registrul Rx direct cu masca */
ORI Rx, MASK