| 
    
      
        | Esercitazioni
          PIC - Assembly |  
 ConclusioniUna domanda comune è:  C o Assembler?  Uno dei principali vantaggi di utilizzare un linguaggio di alto livello (come
  C, Pascal o BASIC) è che il programmatore non deve comprendere l'architettura dell'
  hardware usato, dato che il compilatore provvede a fornire la giusta
  interfaccia alle funzioni del linguaggio attraverso librerie. Così, ad esempio, nell' uso di
  memoria RAM in un microcontroller, questa può essere general purpose o
  condivisa, in banchi di varia dimensione e gestibili in modo diverso a seconda
  dell' hardware; chi scrive un programma di alto livello sa poco o nulla di questa gestione della
  memoria: questo compito è stato delegato a chi ha scritto il compilatore.
  Altrettanto nell' uso di periferiche come UART o I2C.
 Assembly è una programmazione a basso livello; questo vuol dire che il linguaggio non mette a disposizione altro che il set di istruzioni del
  microcontroller. Un microcontroller può svolgere una serie di semplici
  operazioni, generalmente tra 30 e 100
  , ognuna delle quali agisce su un numero di bit pari alla ampiezza
  del bus dati. La concatenazione di queste istruzioni elementari in forme
  logiche adeguate (algoritmi) determina azioni complesse.
 Ad esempio, se ho a disposizione un processore con dati a
  8 bit, per effettuare una operazione di somma su numeri di 16 o 32 bit dovrò
  ripetere più volte le istruzioni elementari su 8 bit, costruendo di un algoritmo. E ogni riga
  assembler riguarda una e
  una sola istruzione.
 
 Con un linguaggio di alto livello, come C o BASIC, ogni riga scritta può
  essere tradotta dal compilatore in molte o moltissime istruzioni; non c'è
  un rapporto diretto tra i due. La scrittura di codice in C o Basic è molto più
  semplice volumetricamente. In particolare, affrontando calcoli (ad es. in
  virgola mobile) o operazioni logiche complesse, il linguaggio ad alto livello
  probabilmente dispone già al suo interno delle funzioni adeguate, cosa che
  non esiste nell' Assembly.
 Per contro, posso comunque utilizzare librerie di funzioni esterne create per
  l' Assembly o posso crearmene di personali a seconda delle necessità.
 In teoria, poi, un programma C può essere ricompilato per funzionare su diversi
  microcontrollori, con un numero limitato di modifiche, mentre un sorgente Assembly, utilizzando le istruzioni
  proprie di un processore specifico, non può essere portato su uno diverso se non
  riscrivendolo completamente. In pratica, però, le differenze di hardware, anche tra elementi
  della stessa famiglia, possono rendere la cosa meno semplice del previsto
  anche per i linguaggi ad alto livello. Oltre al fatto che non esiste "un
  C", ma una pletora di variazioni sullo standard, a volte tali da
  richiedere la riscrittura di ampie parti del sorgente.Inoltre è
  tipico dei microcontroller la necessità di modificare le impostazioni hardware per accedere ad
  IO, impostare timer o utilizzare interfacce di comunicazione seriali; questo significa manipolare i registri di controllo hardware che sono specifici
  di quel tale chip e di cui occorre conoscere le caratteristiche.
 La programmazione con C o BASIC o altri linguaggi evoluti ha l' essenziale
  pregio di derivare da una filosofia propria generalizzabile, ma
  contemporaneamente questo è un grave difetto, dato che fa il possibile per
  nascondere al programmatore la struttura dell' hardware su cui lavora.Se questa situazione è poco rilevante per chi scrive programmi gestionali o
  su personal computer, dove sono disponibili potenti funzioni, librerie e dll, nel caso di una situazione strettamente legata al chip
  ed alle sue periferiche integrate, come nel caso dei microcontroller, la mancata conoscenza delle caratteristiche specifiche di queste
  periferiche può essere uno scoglio ben difficilmente superabile.
 È molto più facile capire l' hardware e come si interfaccia con il resto del
  microcontroller se si inizia con l'imparare l' Assembly, perché questo costringe a
  conoscere di più sul
  dispositivo usato, su come funziona e su come trarne il meglio. Dopo aver scritto
  qualcosa in Assembly, sarà possibile affrontare un linguaggio ad alto livello
  in modo molto più cosciente ed efficace.
 
 Questo elemento è particolarmente importante, dato che, in qualsiasi caso, la conoscenza delle
  caratteristiche
  specifiche di un certo microcontroller  è determinante per le possibilità di
  utilizzarlo correttamente; conoscere alla perfezione un linguaggio evoluto, ma non sapere
  come poterlo applicare sullo specifico componente, è, evidentemente, inutile.
  Un chip potrà avere certe risorse di memoria e moduli integrati differenti da un' altro: c'è bisogno di modificare le impostazioni hardware per accedere agli I / O, impostare i timer o utilizzare interfacce di comunicazione, come ad esempio le porte seriali, e questo significa
  la necessità di manipolare i registri di controllo hardware, specifici
  di quel microcontroller, in ogni caso a livello di bit.È molto più facile capire il meccanismo di questi registri e come si interfacciano con il resto del
  microcontroller se si impegna un certo tempo a considerare il linguaggio Assembly,
  che mette in diretto contatto col dispositivo e con il suo funzionamento, con le diverse risorse disponibili e le
  relative limitazioni.
 Da sfatare, poi, come abbiamo accennato, la leggenda della facile portatilità del
  programma tra microcontroller di famiglie molto diverse tra di loro. E, ancor
  più, tra i vari "C" disponibili anche per le stesse famiglie di
  microcontroller, dove le caratteristiche della
  versione del linguaggio possono essere tali da necessitare la riscrittura di
  molte righe.  Certamente C, con la sua offerta di operazioni matematiche, tipi, funzioni,
  cicli for, while, if .. else, è più semplice nell' uso di questi elementi. 
  In Assembly, tipicamente ogni riga del codice ha un suo valore unitario e solo
  in dipendenza delle possibilità dell' Assembler, più linee costituiscono un
  determinato blocco; le " funzioni" devono essere create a seconda delle
  esigenze o ottenute da librerie disponibili. Un algoritmo
  complesso può richiedere la concatenazione di molte linee, anche centinaia.  Per contro, un vantaggio dell'Assembly è che il codice ottenuto può essere il minimo
  possibile e l' impiego di risorse (memoria) minimizzato. Meno istruzioni,
  esecuzione più veloce, cosa che sui piccoli microcontroller, con poche
  risorse disponibili, può diventare l' unica via percorribile per realizzare
  con essi una applicazione pratica. In ultimo possiamo dire che comunemente si ritiene che Assembly sia più "complesso" e
  difficile da imparare del C o del BASIC. Questa impressione è del tutto
  errata.I linguaggi evoluti richiedono un tempo di apprendimento che può essere anche
  molto elevato, in quanto, sono  "complessi", proprio per la particolarità di
  mettere a disposizione molte funzioni e possibilità logiche. Questo
  corrisponde ad una quantità sensibile di regole per applicare correttamente
  tutta questa complessità.
 Per contro Assembly, in sostanza, non richiede che la conoscenza di pochissime regole
  formali e del set di istruzioni usato, cose che sono
        abbastanza semplici e si apprendono in brevissimo tempo.
 Anche la "leggibilità" maggiore del C rispetto all' Assembly o
  viceversa dipende solamente dalle capacità del programmatore, dato che la leggibilità
  intrinseca di un programma BASIC o C, disordinato o privo del supporto di
  adeguati commenti, è molto minore di quella di un sorgente Assembly scritto
  con un minimo di buon senso.Ricordiamo che esiste una gara internazionale che premia il programma in C
  meno comprensibile !
 Certamente un programma Assembly, richiedendo molte più righe di sorgente, se
  non è supportato da macro, subroutines, librerie, può essere più pesante da
  correggere, gestire, mantenere. Ma è sufficiente una forma di lavoro ordinata ed un efficace commento per poter scrivere codice che risulti
  leggibile sia ad altri programmatori come anche a sé stessi dopo qualche
  tempo. Per queste ragioni ha importanza la forma che deve assumere il sorgente per essere un vero
  "lavoro" e non un pasticcio poco sensato (cose queste, assolutamente
  vere per qualsiasi altro linguaggio).
 Quello che realmente "spaventa" il programmatore nato nell' ambiente di
  linguaggi ad alto livello è costituito da due elementi: 
    la necessità di utilizzare le istruzioni del processorela necessità di conoscere come funziona l' hardware Le istruzioni non sono le funzioni del C e se non si hanno a disposizione
  librerie adeguate, l' impresa di scrivere da zero algoritmi complessi con gli
  opcodes può non essere una cosa semplice, sopratutto per il principiante.Ed è certamente (troppo) comune che un programmatore abbia una sufficiente
  conoscenza del linguaggio ad alto livello, ma poca o nulla conoscenza di come
  farlo agire nel manipolare bit di controllo di periferiche; usando le funzioni
  pre programmate del linguaggio può evitare la necessità di conoscere come
  funziona l' UART o l' MSSP, ma se deve scrivere una qualunque applicazioni al
  di fuori delle possibilità di queste funzioni, si trova del tutto spaesato.
 Possiamo concludere che, certamente, a causa della sua essenzialità e semplicità, il linguaggio
  Assembly non può che risultare più difficoltoso
  quando si tratta di manovrare dati complessi (matrici, floating point, ecc), in
  quanto NON comprende alcuna funzione pre definita, come è comune per
  il C, ma
  demanda al programmatore la responsabilità di occuparsi di ogni dettaglio della gestione
  dei registri, della memoria, delle operazioni complesse, oltre che dello sviluppo logico di
  algoritmi, componendo in modo opportuno le istruzioni elementari, il
  che porta a listati piuttosto lunghi rispetto a quelli equivalenti per
  linguaggi più evoluti.Per questi casi la soluzione è disporre di librerie adeguate, che esistono in
  quanto fornite, ad esempio, dal costruttore del microcontroller. Se non
  disponibili, è necessario costruirsele. Con qualche
  tecnica adeguata si possono ridurre i disagi dell' Assembly, ad esempio, facendo uso
  di modularità nella programmazione, realizzando librerie, subroutines e macro
  istruzioni si alleggerisce in modo sensibile il lavoro di programmazione.
 Per contro, Assembly sarà imbattibile in applicazioni su microcontroller con
  risorse limitate e quando si voglia un completo e massimamente efficiente
  controllo dell'hardware (tanto che i linguaggi ad alto livello prevedono la
  possibilità di inserire tratti di codice Assembly).
 
 Quindi, ha senso programmare in C (o altro) quando si è di fronte a strutture
  di una certa estensione, con calcoli matematici o logiche complesse, ma questo
  non permetterà da solo
  di capire il modo in cui il programma agisce sulle diverse risorse disponibili o le sue
  limitazioni se non si impara anche il linguaggio Assembly prima. Iniziare con
  Assembly, comprendere il dispositivo, per poi passare a C, dove è necessario,
  è il nostro consiglio.
 
  
 |