Home > Corso di programmazione, GNU/Linux > Mini-corso di programmazione/2. Vicini al cuore del computer

Mini-corso di programmazione/2. Vicini al cuore del computer

Be’ il titolo è un po’ fuorviante. In realtà andremo vicini al cervello del computer, il processore, detto anche CPU (Central Processing Unit, unità centrale di elaborazione). Il processore è infatti il componente che effettivamente esegue i programmi e coordina il funzionamento di tutto il resto di un sistema. Abbiamo già visto come è fatto un computer.

Schema di un elaboratore

Ma cosa vuol dire di preciso che il processore esegue i programmi? Prima di tutto dobbiamo ricordare la lezione scorsa: il linguaggio dei computer è il sistema di numerazione binario. Con i numeri rappresentati nel sistema binario vengono memorizzati i dati. Ma non solo. Con i numeri si rappresentano anche le operazioni da eseguire sui dati.

Ad esempio se voglio fare l’ordinamento della rubrica telefonica della lezione precedente?

Ma no, che esagerazione!🙂 Il processore non ha istruzioni così complesse. Le istruzioni che il processore possiede sono molto semplici: copia un dato dalla memoria dentro il processore; somma un numero ad un altro, inverti i bit di un numero, sposta tutti i bit a sinistra o a destra di un posto e cose del genere. Ci sono processori che non hanno neppure un’istruzione per la moltiplicazione o la divisione. In questo caso bisogna ripetere un certo numero di volte l’addizione (in fondo 3 x 5 significa 3 sommato a se stesso 5 volte) o la sottrazione.

E quindi come si fa? I programmi saranno molto complicati!

Sì, è vero. E poi andrebbero scritti con tanti 0 e 1, cioè nel cosiddetto “linguaggio macchina”. Una noia. Per fortuna esiste un linguaggio che ci permette di evitare di scrivere lunghe catene di numeri binari ma usare parole. Questo linguaggio è l’Assembly (a volte chiamato Assembler, ma in realtà l’Assembler è il programma che converte un sorgente in assembly in un programma eseguibile). Il linguaggio è fatto in modo che ad ogni istruzione in linguaggio macchina corrisponda una istruzione in linguaggio Assembly.

Mi fai un esempio?

Certamente. Questo è un programma in assembly per i processori Intel x86….

Un momento, ma perché esistono tanti linguaggi assembly?

Sì. Ogni processore, o meglio ogni famiglia di processori, ha il suo linguaggio. I processori dei personal computer sono x86 e hanno un certo linguaggio. I vecchi Mac usavano processori Motorola che avevano un altro linguaggio. Il venerato Commodore 64 aveva anch’esso un suo linguaggio, e così via.

Ma allora come si fa a far girare un programma di un computer su un altro?

Semplice: non si fa. O almeno non con l’Assembly. Ma procediamo con ordine. Questo è un esempio di programma.

section .data
        hello:     db 'Ciao mondo!',10
        helloLen:  equ $-hello

section .text

global _start

_start:

    mov eax,4
    mov ebx,1
    mov ecx,hello
    mov edx,helloLen
    int 80h

    mov eax,1
    mov ebx,0
    int 80h

Complicato eh?

Sì è arabo!

Invece no, è semplice. L’Assembly è un linguaggio molto molto semplice. Vediamo. Nella prima parte (section .data) creiamo la “stringa” (cioè un insieme di caratteri) contenente il messaggio “Ciao mondo!”. Come vedi alla fine mettiamo 10, cioè “a capo”.

Poi definiamo la lunghezza della stringa. Questa parte del programma non contiene in realtà istruzioni assembly ma solo direttive al programma assemblatore (il “traduttore” da Assembly a linguaggio macchina).

Il cuore del programma inizia invece dopo “_start”. Il nostro scopo, l’avrai capito, è stampare a video la frase “Ciao mondo!”.

Ma non capisco tutti questi mov, int… non c’è una istruzione tipo “stampa questa frase”?

No, non c’è. Non esiste in Assembly. Scrivere a video infatti non è direttamente compito del processore, ma del chip video. Quello che è – almeno apparentemente – un compito banale, cioè scrivere una frase, è in realtà qualcosa di abbastanza complesso a livello “basso”, cioè vicino all’hardware.

Devi però sapere una cosa: il processore “vede” le periferiche, come appunto la scheda video, come una parte della memoria. In alcuni casi si tratta di indirizzi “ad hoc” per le periferiche, in altri casi invece vengono viste proprio come se fosse la memoria RAM. Scrivere sul video quindi significa fondamentalmente scrivere dei caratteri in certe celle della memoria.

Ora noi potremmo anche fare così. Ma chi ci dice che scriveremmo nel posto giusto? E se una certa scheda video si posiziona in una zona differente di memoria? Mmm… complicato.

E quindi come si fa?

Be’ forse ti ricordi quando parlammo di cos’è un sistema operativo. Uno dei compiti di un sistema operativo, e in particolare del kernel (la parte più “bassa” del sistema operativo), ma non solo, è quello di “virtualizzare” l’hardware sottostante. Cioè di permettere ai programmi di disinteressarsi della “ferraglia” su cui stanno girando.

In pratica mi stai dicendo che a stampare a video ci pensa il kernel?

Sì, precisamente. Le istruzioni del programma Assembly che hai visto semplicemente chiamano il kernel e gli danno in pasto i dati che gli servono (dove inizia la stringa e quanto e lunga), poi ci pensa lui a stamparla.

E dove precisamente succede che il programma chiama il kernel?

Succede con l’istruzione “int 80h” (la “h” vuol dire esadecimale). Questa istruzione fa “saltare” il processore verso una parte interna del kernel, poi il kernel stampa la frase e ritorna al programma.

Ah bello! Quindi con il kernel si fa tutto?

No, se fosse così il kernel sarebbe enorme e dovendo stare tutto in RAM richiederebbe una quantità spaventosa. Inoltre nel caso di un kernel come Linux, che è di tipo monolitico, cioè “tutto di un pezzo” basterebbe un piccolo errore per mandare in crash l’intero sistema.

Probabilmente ti saranno capitate delle schermate blu su Windows e forse anche dei blocchi totali su GNU/Linux. Be’ il motivo è che c’è stato un errore a livello del kernel. Nel caso di Linux se l’errore è nel kernel le spie della tastiera lampeggiano.

Ok, però io vedo due volte l’istruzione int 80h.

Sì, la seconda chiama il kernel per dirgli che deve terminare il programma.

Ma quindi cosa può fare il kernel? Fino a che punto si spinge?

Il realtà le funzioni che il kernel “espone” all’esterno sono abbastanza poche. Meno di 400 nel caso del kernel Linux. Queste funzioni, dette “chiamate di sistema” che possono essere invocate con l’istruzione int 80h, servono in larga parte per dialogare con l’hardware: stampare a video, creare un file, montare una partizione, oppure per creare un nuovo processo.

Quindi il kernel è molto semplice?

No, il kernel è piuttosto complicato, perché l’hardware da gestire è tanto. Inoltre nel caso di Linux abbiamo tante variabili da considerare. Ad esempio Linux implementa una miriade di filesystem diversi come ext2, ext3 ed etx4 (che sono i principali) ma anche fat32, btrfs, xfs, reiserfs e tanti altri. Ognuno di questi ha un pezzo di kernel che li gestisce ma quando un programma deve scrivere un file non se ne preoccupa: la funzione del kernel che userà è sempre la stessa. Sarà poi il kernel a controllare dove si sta scrivendo il file e adottare il sistema giusto.

Ah ecco, così mi è più chiaro. In pratica il kernel crea una realtà virtuale.

Esattamente.

Quindi per le necessità più complesse, cosa si fa?

Ti faccio un esempio. Abbiamo visto che il kernel sa stampare una stringa di caratteri. Se invece vogliamo stampare un numero?

Ma se il numero è fatto di una serie di caratteri non ci sono problemi no?

Sì, ma se invece non lo è? Se invece lo abbiamo memorizzato davvero come numero? Ricordi che abbiamo visto che i computer memorizzano i numeri in formato binario. Abbiamo già detto che ogni cifra binaria che può essere 0 oppure 1 si chiama “bit”. Un insieme di 8 bit forma un byte. Con un byte possiamo rappresentare numeri da 0 a 255. Diciamo che in una celletta della memoria abbiamo scritto il numero 01100111 che in decimale è ….

Aspetta che uso la calcolatrice…

Dai è facile! 1+2+4+32+64 = 103.

E vabe’ dammi il tempo!

Allora diciamo che abbiamo questo numero. Come lo stampiamo?

Chiamiamo il kernel e lui lo stampa.

No. magari🙂 il kernel prende il 103 e ti stampa il carattere ASCII corrispondente al 103 che è la lettera “g” minuscola. Per lui quello è un byte qualsiasi, non una stringa con dentro i caratteri “1”, “0” e “3”.

E allora? Bisogna trasformare il numero in una stringa?

Giusto. E per farlo bisogna fare così: si prende il numero e lo si divide per 10, e si prende il resto. 103/10 = 10 con il resto di 3. Poi si divide il risultato nuovamente per 10, quindi 10/10=1 con il resto di 0. Poi si prende di nuovo il quoziente (cioè 1) e lo si divide per 10 ancora. Quindi 1/10=0 con il resto di 1. E ci si ferma perché siamo arrivati a 0.

Adesso abbiamo le cifre… 3 0 1.

Sì, quindi bisogna prenderle dall’ultima alla prima. E poi non basta ancora.

Come non basta?

E no perché se diamo al kernel i numeri così lui stamperà il carattere ASCII corrispondente a 1 a 0 e a 3. Dobbiamo prima sommare a ciascuno il codice ASCII del carattere “0”, cioè 48. Quindi 48+1=49, 48+0=48, 48+3=51. Ora possiamo dare al kernel la nostra stringa, ricordando però che dobbiamo anche contare la sua lunghezza.

Ma è complicatissimo!

Già. Per questo nessuno scrive programmi in Assembly se non in casi particolari.

E quindi … si usa il C!

Bravo. Il C o comunque un linguaggio ad “alto livello”. In gergo un linguaggio è detto “ad alto livello” se è più vicino al linguaggio umano, e quindi al modo di ragionare dell’uomo, che a quello del processore. In realtà il C è un linguaggio ad alto livello che però cerca di rimanere abbastanza aderente alla macchina, infatti qualcuno lo ha definito un “assembly portabile”.

Portabile in che senso?

Nel senso che un programma in C può essere tradotto nel linguaggio di tutti i processori. Mentre un programma in Assembly funzionerà solo su un tipo di processore, quello per cui è stato scritto. In effetti, questo è proprio il motivo per cui esiste il C.

Spiegati meglio.

Be’ il C nacque quando la AT&T, la compagnia dei telefoni americana, ebbe la necessità di eseguire il sistema operativo Unix su computer differenti. Unix, il progenitore di GNU/Linux, era nato da poco e gli stessi creatori di unix crearono il C. Per questo GNU/Linux e tutti i sistemi simili a Unix hanno un rapporto privilegiato con il C. E’ il linguaggio principe per questo sistema operativo. Tutti i principali componenti di GNU/Linux sono scritti in C ed anche tante, tantissime applicazioni. Se vuoi saperne di più sulla storia di Unix, qui ho fatto un riassunto.

Quindi in C non sarà costretto a questo lavoraccio?

E sì, meno male. In C esiste una sola istruzione per stampare numeri, stringhe, singoli caratteri. Non solo. Prima abbiamo visto il caso dei numeri interi. Ma i numeri con la virgola? La cosa diventa ancora più complicata.

E allora perché tutta questa storia? Potevi direttamente passare a spiegare il C se è più semplice!

Certo, ma non avresti capito come fa il C poi a fare quello che fa. Ma soprattutto non avresti capito perché, quando usi questa istruzione del C che “fa tutto”, però devi dirle che tipo di dato le vuoi fare stampare.

Ah, ma come si chiama questa istruzione?

Si chiama printf(). Ma ci sono da dire altre cose da dire prima di arrivarci. Tu però tieni a mente questa lezione: quello che a te sembra semplice, per un computer è complicatissimo.

La terrò a mente…

Bene, allora alla prossima lezione.

Ma devo studiarmi l’Assembly adesso? Così capisco meglio il C?

No, non è necessario. Ma ogni volta che spiegherò qualcosa del C che ha un diretto corrispettivo nell’Assembly, allora te lo mostrerò. Ciao🙂

  1. lorenzo
    17 marzo 2010 alle 8:48
  2. Alessandro
    17 marzo 2010 alle 9:18

    Solo un appunto che sono sicuro tu guido sai ma altri utenti magari no, anche le sottrazioni in realtà non sono altre che somme algebriche con numeri negativi. Quindi possiamo dire che i processori implementano solo l’ istruzione di somma. Una sottrazione è comunque una somma con un un numero relativo minore di 0, e si capisce se un numero è negativo da un bit detto di segno ;D

    • 17 marzo 2010 alle 10:59

      sì ma ci sono processori che non hanno l’istruzione “sub”, quindi per fare la sottrazione devi essere tu a rendere negativo il numero (di solito in complemento a 2).
      Ma a parte questo i processori hanno circuiti dedicati alle operazioni matematiche (oltre al fatto che integrano il coprocessore matematico che prima era separato, ma ha un suo set di istruzioni e non c’entra con il set di istruzioni del processore in quanto tale).

      • Alessandro
        17 marzo 2010 alle 13:51

        eh sai quando ho studiato queste cose a scuola l’ alu era separata e non spesso usata quindi complemento a due e tutte somme ;D
        Spesso fatto anche per esercizi per capire come funzionava bene il basso livello, una palla ma se non altro è servito

        • 17 marzo 2010 alle 14:43

          Non credo, l’alu non è mai stata separata, è sempre stata parte della CPU.

          • Alessandro
            17 marzo 2010 alle 21:55

            probabile abbia detto una cazzata, però son quasi sicuro mi hanno insegnato che il pc fa solo somme come calcolci e non riesce a fare sottrazionei direttamente ma appunto complemento a 2 e poi somme

          • 18 marzo 2010 alle 11:10

            be’ negli anni 80 sì, oggi no.

  3. juhan
    17 marzo 2010 alle 10:16

    Guido sei un ottimo maestro🙂 Bella l’idea del dialogo con lo studente (un po’ petulante).
    In effetti quando ho cominciato a lavorare con i PC M$ (e a volte anche Borland) consigliava di usare l’assembler (dai lo chiamano tutti così). Ma io non mi sono mai arreso a scendere tanto in basso.

  4. Danielsan
    17 marzo 2010 alle 10:29

    Ma sei un mito, le leggo anche solo per il gusto di leggerle!

  5. ezo
    17 marzo 2010 alle 20:44

    si sei bravo complimenti. è anche divertente.

  6. Mario
    17 marzo 2010 alle 23:59

    Guio la prossima lezione sarà di microprogrammazione?😄😄

  7. Alessandro
    18 marzo 2010 alle 13:08

    ahaha infatti basta micro controllori, quando abbiamo ottime cpu tutto integrato ;D

    E poi il futuro è dei linguaggi ad alo livello sempre più ;D

  8. 18 marzo 2010 alle 17:55

    Grazie !!! Era proprio quello che cercavo: una guida semplice e chiara. Aspetto con ansia le prossime lezioni.

  9. -luk-
    18 marzo 2010 alle 22:52

    Complimenti, ottima guida Guiodic!

  10. dreros
    19 marzo 2010 alle 12:49

    cosiglio di usare il linguaggio lc-2 per comprendere “la stupidita” del processore nel trattare i dati.
    Per scrivere in questo linguaggio bisogna conoscere che la cpu ragiona in “complemento ad 1”

    • dreros
      20 marzo 2010 alle 10:07

      mi corrego. Complemento a 2.

  11. KillJoy
    22 marzo 2010 alle 1:05

    Ciao Guido è sempre un piacere leggere il tuo blog, potrsti per chi vuole, consigliare di studiare questo e questo (dare una letta almeno) e se è possibile esercitarsi con questo e quello per poter capire meglio il tutto??
    O come sempre ho detto una cazzata.-D

  12. 30 marzo 2010 alle 1:24

    Belàn Guido…sempre più interessante😀

  13. Adriano
    12 aprile 2010 alle 14:48

    A quando la nuova lezione?

    • 16 aprile 2010 alle 14:22

      presto. ho avuto poco tempo negli ultimi giorni

  14. Mauro
    4 ottobre 2010 alle 18:32

    Toh la coincidenza!
    http://www.askreamaor.com/programming/assembly-language/
    Citare le fonti no eh?

    • 4 ottobre 2010 alle 19:31

      fonte di cosa? quello è un hello word, è identico su migliaia di siti e guide, non è che c’è un inventore privilegiato da citare, altrimenti dovrei citarne migliaia.

  15. 10 maggio 2011 alle 19:54

    Say thanks for a especially clear and useful post. I am most certainly a violator of lots of these rules. I typically unearth me personally conflicted when creating a blog submit because I see myself personally writing more than folks choose to learn, but I really feel that I should do the topic matter justice by completely protecting it. I believe that by pursuing a number of these procedures I stop up cutting out crucial aspects on the discussion. I guess you could have to uncover a stability.

  16. 24 giugno 2013 alle 0:13

    This excellent website definitely has all of the info I needed about this subject
    and didn’t know who to ask.

  17. 17 ottobre 2013 alle 22:05

    Inspiuring quest there. What haqppened after? Good luck!

  18. 11 agosto 2014 alle 7:16

    Quality posts is the secret to be a focus for the people to visit the site, that’s what this web page is providing.

  19. 11 agosto 2014 alle 21:47

    Quality content is the main to interest the people to go to see the site, that’s what this web page is providing.

  1. No trackbacks yet.

Lascia un commento

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione / Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione / Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione / Modifica )

Google+ photo

Stai commentando usando il tuo account Google+. Chiudi sessione / Modifica )

Connessione a %s...

%d blogger cliccano Mi Piace per questo: