naslovna_asemler_asemblersko_programiranje_intel8051_mikrokontroleri_tutorijali_automatika.rs.jpgAsembler je programski jezik koji mašinski jezik specifične procesorske arhitekture predstavlja u ljudima čitljivom obliku. Iz toga proizilazi da svaka procesorska arhitektura posjeduje svoj asembler. Programi napisani u asembleru se odlikuju mogućnošću slanja direktnih komandi procesoru kao i iskorišćavanju celog dijapazona arhitekture. Pošto rade na nivou mašinskog koda, mnogo su manji i brži od programa napisanih u nekom konvencionalnom programskom jeziku. U ovom članku nam je bila želja da čitaoce upoznamo sa principima asemblerskog programiranja na arhitekturi Intel 8051.

  Set instrukcija za 8051 obuhvata ukupno 111 instrukcija, od kojih je 49 jednobajtnih, 45 dvobajtnih i 17 trobajtnih. Ako se uzmu u obzir i varijante istih instrukcija (na primer ista instrukcija primenjena na različite registre iz registarske banke), ukupno postoji 255 instrukcija. Generalni format koji važi u svakom asembleru za ove instrukcije je sledeći (mada postoje i varijacije u ovom formatu):
mnemonik    odredište, izvor
  Mnemonik nosi kod instrukcije, a operandi odredište i izvor samo nose podatke ili adresu odakle se uzimaju podaci nad kojima se vrši operacija. Ako postoje dva operanda, onda se rezultat operacije uvek smešta u prvi koji je naveden. Recimo, ako instrukcija glasi ADD A,B to je isto kao da smo u nekom višem programskom jeziku napisali A=A+B.
U tabelama koje slede, dato je vreme izvršenja instrukcije u mikrosekundama. Ta vremena su tačna ako mikrokontroler radi na taktu od 12MHz. Ako mikrokontroler treba da radi na nekom drugom taktu, taj podatak treba shvatiti kao broj mašinskih ciklusa potrebnih za izvršenje instrukcije, a trajanje mašinskog ciklusa iznost TC=12/fosc gde je fosc frekvencija takta mikrokontrolera.
tabela1_asemler_asemblersko_programiranje_intel8051_mikrokontroleri_tutorijali_automatika.rs.jpg
Tabela 1. Prenos podataka instrukcijama koje pristupaju internoj memoriji
tabela2_asemler_asemblersko_programiranje_intel8051_mikrokontroleri_tutorijali_automatika.rs.jpg
Tabela 2. Prenos podataka sa instrukcijama koje pristupaju spoljašnjoj memoriji
tabela3_asemler_asemblersko_programiranje_intel8051_mikrokontroleri_tutorijali_automatika.rs.jpg
Tabela 3. Instrukcije za čitanje lookup tabele
  Kod instrukcija iz grupe prenosa podataka (MOV, MOVC i MOVX) zarez između operanda možemo da shvatimo kao strelicu nalevo, jer se uvek sadržina drugog operanda upisuje u prvi, pri čemu se drugi ne menja. Ovo ne važi za instrukcije XCH i XCHD, gde operandi međusobno izmenjuju vrednosti (kod XCHD samo četiri najniža bita).
  Sve instrukcije iz ove grupe obavljaju prenos 8-bitnog podatka, sa dva izuzetka: XCHD vrši razmenu 4-bitnog podatka, a MOV DPTR, #data upisuje 16-bitnu vrednost u registre DPH i DPL.
Instrukcije čija svrha je upis bajta iz programske memorije ili komunikacija sa spoljnim RAM-om imaju 16-bitno adresno polje. Prvi slučaj (upis bajta iz programske memorije u akumulator) se uglavnom koristi za lookup tabele, gde se pozicija u tabeli izračunava iz bazne adrese početka tabele (obično se smešta u DPTR) i ofseta (koji je u akumulatoru), pa je zbog toga ova instrukcija unapred proširena i glasi MOVC A,@A+DPTR. Ona izvršava tačno ono što možemo i da pretpostavimo: najpre sabere 16-bitni DPTR sa 8-bitnim akumulatorom, pa rezultat iskoristi za adresiranje programske memorije, pročita bajt i upiše ga u akumulator. Ako nam treba samo 16-bitno adrsiranje bez ofseta, pre ove instrukcije treba upisati 0 u akumulator (CLR A).
Instrukcija MOVC A, @A+PC radi isto to, ali umesto DPTR uzima 16-bitnu adresu sledeće instrukcije u programu. Sledeći potprogram uzima vrednost člana pod rednim brojem koji je upisan u akumulator (u ovom slučaju od 0 do 4), iz tabele koja sledi odmah iza potprograma:

REL_PC:        INC      A
MOVC A, @A+PC
RET

DB    27h
DB    41h
DB    00h
DB    5Eh
DB    7Fh

Instrukcija INC A je potrebna da bi se u kalkulaciji preskočila instrukcija RET, koja u programu zauzima jedan bajt. Ako ovde ima još koda, onda broj njegovih bajtova treba sabrati sa akumulatorom.

Instrukcije koje komuniciraju sa spoljnim RAM-om (MOVX) mogu svoje 16-bitno adresno polje da uzmu iz DPTR, ili kombinovanjem P2 (viši bajt) i R0 ili Rl (niži bajt).
Nijedna od instrukcija iz ove grupe ne utiče na flegove, izuzev POP i MOV instrukcija kojima je prvi operand PSW, jer njihova funkcija i jeste izmena sadržaja registra koji sadrži flegove.
Aritmetičke instrukcije 
tabela4_asemler_asemblersko_programiranje_intel8051_mikrokontroleri_tutorijali_automatika.rs.jpg
Tabela 4. Skup aritmetičkih instrukcija
   Mikrokontroler 8051 podržava sve četiri osnovne aritmetičke operacije. Samo osmobitna aritmetika je podržana (sa izuzetkom INC DPTR, koji uvećava stanje 16-bitnog registra), i to sa pozitivnim brojevima, mada overflow fleg omogućava sabiranje i oduzimanje sa predznakom. Sabiranje može da se obavlja i sa binarno kodiranim decimalnim (BCD) brojevima, kod kojih osmobitni registar nosi dve odvojene decimalne cifre, svaku u po 4 bita.
  Sabiranje
  INC (increment) uvećava operand za 1.
ADD sabira akumulator sa izvornim operandom i smešta rezultat u A. Bit C je deveti bit rezultata, zapravo bit prenosa za sabiranje višebajtnih brojeva.
ADDC (ADD with Carry) sabira akumulator sa izvornim operandom i sa bitom C, a rezultat smešta u akumulator.
  Primer sabiranja višebajtnih binarnih brojeva:
Ako treba DPTR sabrati sa 16-bitnim binarnim brojem čiji je viši bajt u R4, a niži u R5 i rezultat smestiti u DPTR, program može da izgleda ovako:

MOV    A, DPL    ; uzmi niži bajt
ADD    A, R5        ; saberi
MOV    DPL, A    ; smesti rezultat nižeg bajta
MOV    A, DPH    ; uzmi viši bajt
ADDC    A, R4        ; saberi i dodaj prenos
MOV    DPH, A    ; smesti rezultat višeg bajta

DA A (Decimal Add Adjust for Addition) koriguje rezultat posle binarnog sabiranja, tako da odgovara za BCD brojeve. Na primer, ako akumulator i registar B sadrže BCD brojeve (00-99) onda će sledeći program sabrati ova dva BCD broja i ispravan BCD rezultat smestiti u akumulator:

ADD    A, B        ; saberi binarno
DA    A        ; koriguj rezultat
Ako je rezultat posle instrukcije DA A veći od 99, tada je bit C (prenos) setovan.
  Oduzimanje
  DEC (decrement) umanjuje operand za 1.
SUBB (subtract with borrow) oduzima drugi operand od prvog (koji je uvek akumulator). Pošto instrukcija SUB (oduzimanje na koje bit C ne utiče) ne postoji u setu za 8051, možemo da ga sintetišemo tako što pre SUBB izvedemo jedno CLR C (C=0).
Oduzimanje višebajtnih binarnih brojeva se vrši slično kao kod sabiranja. Od DPTR treba oduzeti 16-bitni binarni broj čiji je viši bajt u R4, a niži u R5 i rezultat smestiti u DPTR:

MOV    A, DPL    ; uzmi niži bajt
CLR    C        ; da bi SUBB radio kao SUB
SUBB    A, R5        ; oduzmi R5
MOV    DPL, A    ; smesti rezultat nižeg bajta
MOV    A, DPH    ; uzmi viši bajt
SUBB    A, R4        ; oduzmi R4 i prenos
MOV    DPH, A    ; smesti rezultat višeg bajta

  Množenje
  MUL AB množi dva 8-bitna broja bez predznaka, od kojih je jedan smešten u akumulator, a drugi u B registar, i 16-bitni rezultat smešta u akumulator (niži bajt) i registar B (viši bajt). Pošto je ovde rezultat 16-bitni, prekoračenje nije moguće pa je bit C uvek resetovan, a bit OV je setovan ako je rezultat veći od 255 (odnosno ako je registar B veći od 0), a resetovan ako je B=0.
  Deljenje
  DIV AB deli akumulator sa registrom B i celobrojni rezultat smešta u A, a ostatak deljenja u B. Deljenje sa nulom (ako je B=0) rezultira sa nepredvidivim sadržajem registara, i u tom slučaju bit OV će biti setovan. Inače, u normalnom slučaju (kad je B>0) bitovi OV i C su resetovani.
Logičke instrukcije
tabela5_asemler_asemblersko_programiranje_intel8051_mikrokontroleri_tutorijali_automatika.rs.jpg
tabela6_asemler_asemblersko_programiranje_intel8051_mikrokontroleri_tutorijali_automatika.rs.jpg
Tabele 5. i 6. Skup logičkih instrukcija
  CLR resetuje navedeni bit, a CLR A resetuje sve bitove u akumulatoru.
  CPL komplementira navedeni bit (menja mu stanje), a CPL A komplementira sve bitove u akumulatoru.
  SETB setuje navedeni bit.
   RL (RR) rotira nalevo (nadesno) akumulator. Bit 7 (bit 0) dolazi na mesto bita 0 (bita 7). Bit koji izlazi sa krajnje pozicije i ulazi sa druge strane, kopira se i u prenos C.
RLC (RRC) rotira nalevo (nadesno) akumulator kroz bit C (9-bitna rotacija). Tako će bit C da se preseli u bit 0 (bit 7), a bit 7 (bit 0) u bit C.
SWAP rotira akumulator 4 puta nalevo (odnosno na desno), tj. vrši zamenu nižeg i višeg nibla akumulatora.
ANL izvodi logičku operaciju AND između prvog i drugog operanda, a rezultat smešta u prvi operand. Ova operacija je moguća sa operandima koji zauzimaju jedan bajt ili jedan bit.
ORL izvodi logičku operaciju OR između prvog i drugog operanda, a rezultat smešta u prvi operand. Ova operacija je moguća sa operandima koji zauzimaju jedan bajt ili jedan bit.
XRL izvodi logičku operaciju XOR između prvog i drugog operanda (oba su 8-bitna), a rezultat smešta u prvi operand.
Potprogrami
  ACALL (Absolute Call) i LCALL (Long Call) pozivaju potprograme na sledeći način: najpre 16-bitnu adresu sledeće instrukcije u programu stave na stek i uvećaju SP za dva, a onda u PC upišu pridruženu adresu. Ta adresa u slučaju poziva ACALL može da se nađe samo u istom bloku od 2K u kome je i prva instrukcija posle poziva (ona koja se stavlja na stek), a kod LCALL nema ograničenja, jer je adresa 16-bitna. Razlog za ograničenje kod ACALL je taj što ova instrukcija zauzima samo 2 bajta (prema 3 bajta koje zauzima LCALL), i 5 bitova zauzima kod instrukcije, pa tako za adresno polje ostaje samo 11 bitova.
RET izaziva akciju koja je inverzna instrukciji ACALL odnosno LCALL: sa steka se uzimaju dva bajta i smeštaju u programski brojač. SP se umanjuje za dva. To je povratak iz potprograma, jer će posle ovoga program nastaviti da se izvršava od instrukcije koja je sledila iza poziva.
  RETI radi isto što i RET, samo što se uz to omogućava i prekid tekućeg nivoa prioriteta. Ovo je standardna instrukcija za povratak iz prekidnog potprograma.
Bezuslovni skokovi
tabela7_asemler_asemblersko_programiranje_intel8051_mikrokontroleri_tutorijali_automatika.rs.jpg
 Tabela 7. Skup instrukcija bezuslovnog skoka
  AJMP (Absolute jump) i LJMP (Long Jump) prenose pridruženu adresu u programski brojač, tako da će program nastaviti da se izvršava nadalje od te adrese. AJMP i LJMP su po broju bitova adrese analogni pozivima potprograma ACALL i LCALL.
SJMP (Short jump) je dvobajtna instrukcija koja omogućava skokove u opsegu -128 do +127 u odnosu na sledeću instrukciju u programu. Sem dužine skoka, razlika između SJMP i AJMP je u tome što SJMP može da preskoči blok od 2KB, dok AJMP uvek skače unutar ovakvog bloka.
U tabeli, kod instrukcije “JMP addr”, reč JMP se odnosi na sve tri instrukcije skoka, AJMP, LJMP i SJMP.
JMP @A+DPTR skače na adresu koja se izračunava tako što se sabere 16-bitni registar DPTR sa ofsetom koji se nalazi u akumulatoru. Ovo je od koristi kod složenih grananja u potprogramu, kad od stanja akumulatora zavisi na koju adresu treba izvesti skok (tabelarni skokovi). Sledeći program će izvesti skok na jednu od lokacija iz tabele JP_TAB, zavisno od stanja akumulatora na ulazu:

MOV    B,3            ; priprema za  množenje
MUL    AB            ; A = A*3, jer je dužina LJMP
; instrukcije 3 bajta
MOV    DPTR,#JP_TAB
JMP    @A+DPTR        ; skok na željeno mesto
JP_TAB:
LJMP SERVICE_A
LJMP SERVICE_B
LJMP SERVICE_C
LJMP SERVICE_D

Svaka instrukcija u tabeli mora da zauzme po 3 bajta, a posebnu pažnju treba obratiti da akumulator na ulazu nema vrednost veću od broja članova tabele umanjenog za 1 (u ovom primeru A mora da bude u opsegu od 0 do 3, jer ima 4 instrukcije skoka).

Uslovni skokovi
tabela8_asemler_asemblersko_programiranje_intel8051_mikrokontroleri_tutorijali_automatika.rs.jpg
Tabela 8. Skup instrukcija uslovnog skoka
  Svi uslovni skokovi su mogući samo u opsegu -128 do +127 u odnosu na sledeću instrukciju u programu, kao što je slučaj kod SJMP. Ako je potrebno skočiti na neku dalju tačku, treba blizu uslovnog skoka postaviti repetitor, koji se sastoji od instrukcije AJMP ili LJMP, i onda izvesti kratki uslovni skok na repetitor. Druga mogućnost je da se komplementira uslov i preskoči repetitor, kao u ovom primeru, koji zamenjuje skok JZ  FAR_LAB:
instrukcija:
JZ    FAR_LAB
se zamenjuje sekvencom:
JNZ    LAB1
LJMP    FAR_LAB
LAB1:

Instrukcije za uslovne skokove:

JZ (Jump on Zero) izvršava skok ako je akumulator jednak nuli
JNZ (Jump on Not Zero) izvršava skok ako je akumulator različit od nule
JC (Jump on Carry) izvršava skok ako je flag C setovan
JNC (Jump on Not Carry) izvršava skok ako je fleg C resetovan
JB(Jump on Bit) izvršava skok ako je navedeni bit setovan
JNB (jump on Not Bit) izvršava skok ako je navedeni bit resetovan
JBC (Jump on Bit and Clear bit) izvršava skok ako je navedeni bit setovan i istovremeno resetuje navedeni bit
CJNE (Compare and jump if Not Equal) poredi prvi operand sa drugim i skače ako su različiti. Bit C će biti setovan ako je prvi operand manji od drugog, u suprotnom biće resetovan.
DJNZ (Decrement and jump if Not Zero) umanjuje operand za 1, a ako je posle umanjenja operand različit od nule, skače na navedenu adresu, dok u suprotnom ignoriše skok i nastavlja izvršenje programa od sledeće instrukcije (slično instrukciji LOOP kod mikroprocesora 8086).

Uticaj instrukcija na flegove
  U toku izrade programa od velike je važnosti znati na koji način instrukcije utiču na flegove u PSW registru. Neke instrukcije uopšte ne utiču na flegove C (carry), OV (overflow) i AC (auxiliary carry), zato i nisu prikazane u tabeli.
tabela9_asemler_asemblersko_programiranje_intel8051_mikrokontroleri_tutorijali_automatika.rs.jpg
Tabela 9.
  Legenda:
–   instrukcija ne utiče na fleg
0  instrukcija resetuje fleg
1  instrukcija setuje fleg
X  fleg se menja zavisno od rezultata operacije
Napomena: instrukcije koje direktno menjaju sadržaj registra PSW će uticati na flegove, bez obzira što ovde nisu navedene.
Preostala dva flega: P (parnost) i Z (zero) nisu fizički implementirani u PSW registru kao flip-flopovi, nego su zapravo grupe logičkih kola koje testiraju stanje akumulatora. Tako će izlaz iz logike za fleg P biti visok ako je broj setovanih bita u akumulatoru paran, a za fleg Z ako su svi biti u akumulatoru jednaki nuli. Prema tome, nema nikakvog smisla navoditi kako instrukcije utiču na ove flegove, jer to zavisi samo od trenutnog stanja akumulatora.
Literatura:
 

 

Fakultet tehničkih nauka, Katedra za elektroniku

POSTAVI ODGOVOR

Please enter your comment!
Please enter your name here

This site uses Akismet to reduce spam. Learn how your comment data is processed.