Come viene eseguito un programma a livello di CPU?


14

So che questa è una domanda molto comune. Ma ho un'angolazione diversa nella mia mente. Proverò solo ad articolarlo qui.

Da quello che so, ogni istruzione eseguita da una CPU è nel linguaggio macchina e tutto ciò che la CPU può fare è eseguire alcune operazioni aritmetiche grazie a ALU e ai suoi transistor (se andiamo a livello hardware).

Tuttavia, questo è più facile da scrivere che da comprenderlo. Quindi, se tutta la CPU fa l'aggiunta, la sottrazione, ecc., Allora come sta un programma, ad esempio un programma JAVA che dice print Hello World, eseguito con queste operazioni aritmetiche?

Voglio dire, come viene convertito questo programma in qualcosa che è solo un'aggiunta per la CPU?

PS Se questa domanda non è applicabile per questo sito Web, mi scuso.

-----Seconda parte-----

Va bene. Grazie a tutti per aver risposto così velocemente e con questo entusiasmo. Ho pensato che fosse meglio modificare un po 'la mia domanda piuttosto che andare a commentare tutte le risposte e a farle di nuovo.

Quindi eccolo qui.

In primo luogo, tutti hanno risposto specificamente agli esempi di Hello World. È colpa mia. Avrei dovuto mantenere questo generico. L'esempio Hello world mette in discussione i dispositivi di output e il modo in cui la sua elaborazione non è limitata alla CPU, che è giustamente menzionata nelle tue risposte.

Inoltre, molti di voi hanno notato che la CPU fa molto di più di una semplice aggiunta. Sono d'accordo. Non l'ho scritto e l'ho assunto fino in fondo. Da quello che ho capito, questo è il processo:

  1. leggere le istruzioni dalla memoria (utilizzando bus dati e indirizzi e roba contatore programmi)

    1. memorizzare i dati nel registro all'interno della CPU
    2. Ora ALU esegue operazioni aritmetiche, ovviamente dopo aver decodificato l'istruzione, o fa un salto se è un'istruzione if like
    3. E poi comunicare con altre risorse se necessario come con il dispositivo di output e così via. I processi oltre questo sono banali per ora.

Quindi nel passaggio 3 in cui la CPU decodifica un'istruzione e decide di eseguire un'operazione aritmetica (qui stiamo assumendo che non ci siano altre operazioni da fare come saltare le istruzioni correnti ... poiché le operazioni aritmetiche sono per lo più eseguite ... quindi ci atterremo a quello ) Qui finisce la mia visualizzazione. Come un'istruzione del mio programma sia solo un'operazione aritmetica per la CPU. Fa quell'operazione aritmetica e quell'istruzione serve al suo scopo.

Spero di essermi chiarito questa volta.

PS Sto assumendo qui un grande presupposto che ALU non sia limitato all'effettiva operazione aritmetica che facciamo nei nostri programmi, piuttosto esegue tutte le istruzioni, che ora sono in forma binaria, aggiungendole o sottraendole ecc. Per ottenere il risultato che sono destinate cedere. Se sbaglio qui delle risposte di seguito rispondi correttamente alla mia domanda.


Comprendo che il compilatore converte il programma in linguaggio macchina. Non riesco a visualizzare un programma come un'operazione aritmetica. Anche se se il programma stesso prevede l'aggiunta di due numeri, è comprensibile, ma per il resto no ... sì !! :)
user2827893

1
Forse dovresti iniziare a guardare il set di istruzioni effettivo delle CPU, ad esempio quelle molto semplici come MC6502, Z80 ... quindi vedere che ci sono istruzioni di accesso alla memoria, istruzioni di elaborazione dei dati, rami ... Potresti quindi indovinare come possono essere combinato per l'implementazione di qualsiasi algoritmo.
TEMLIB,

3
Una CPU sicuramente può fare più dell'aggiunta. È fondamentale ricordare che una CPU può fare confronti e salti.
Theodoros Chatzigiannakis,

1
(Sembra) stai ancora rifiutando fermamente di vedere IF (prendere una decisione) e MOVE (leggere e memorizzare dati), la programmazione è del 99% IF e MOVE. L'aritmetica è comprensibile. Il tuo primo esempio (Hello world) non ha alcuna aritmetica.
edc65,

1
1. Penso che avresti maggiori probabilità di ottenere buone risposte se facessi una nuova domanda con la tua nuova confusione, piuttosto che modificarla per cambiare ciò che stai chiedendo. Hai delle buone risposte alla tua domanda originale e la tua domanda originale sembra che possa resistere da sola, quindi perché non rimuovere la modifica e porre una nuova domanda? 2. Detto questo, non riesco a capire la nuova parte. Qual è esattamente la tua domanda sulla nuova parte? Quando si dice "questo è dove finisce la mia visualizzazione", vuoi dire che si fa a capire il punto 3, o non si capisce il punto 3? Se lo fai, cosa non capisci?
DW

Risposte:


7

Puoi provare a prendere un semplice programma e compilarlo nel codice macchina nativo. (Java normalmente si compila nel codice JVM, ma Andrew Tennenbaum ha un libro in cui descrive come progettare una CPU che funzioni in modo nativo, quindi lo farà.) Su GCC, ad esempio, si dà al compilatore lo -Sswitch.

Questo ti dirà che qualsiasi cosa delicata, come l'I / O, viene implementata chiamando il sistema operativo. Mentre potresti scaricare il sorgente sul kernel Linux e fare lo stesso con esso, quello che sta succedendo è: tutto sta manipolando lo stato della memoria del computer, ad esempio l'elenco dei processi in esecuzione, oppure parlando con l'hardware usando indirizzi di memoria speciali che lo controllano o utilizzando istruzioni speciali della CPU come ine outsu x86. In genere, tuttavia, solo programmi speciali chiamati driver di dispositivo parleranno con un determinato hardware e il sistema operativo invierà richieste per utilizzare l'hardware con il driver giusto.

In particolare, se si stampa, "ciao, mondo!" il compilatore lo trasformerà in un insieme di istruzioni che carica la stringa in una posizione particolare (ad esempio, caricando l'indirizzo della stringa in memoria nel %rdiregistro) e chiamando una funzione di libreria con l' callistruzione. Questa funzione di libreria potrebbe trovare la lunghezza della stringa con un ciclo, quindi chiamare la chiamata di sistemawrite()per scrivere quel numero di byte dalla stringa nel descrittore di file numero 1, che è l'output standard. A quel punto, il sistema operativo cerca quale sia il file numero 1 di quel processo e decide cosa significa scrivere. Se le scritture sullo standard output vengono stampate sullo schermo, ci sarà un processo come la copia dei byte in un buffer, che viene poi letto dal programma terminale, che dice al sistema di finestre quali lettere mettere dove in quale font. Il sistema a finestre decide esattamente come dovrebbe apparire e dice a un driver di dispositivo di mettere i pixel sullo schermo, cosa che fa cambiando la memoria video.


Grazie @Lorehead. Questa spiegazione sembra buona, ciao esempio del mondo.
user2827893

5

La tua CPU in sé è stupida, come hai capito. Ma c'è un microcosmo di chip hardware attorno ad esso. Hai un'istruzione che ti consente di impostare una linea della CPU ad alto livello che è collegata a un altro chip. Quel chip hardware controlla la linea e dice: "Ehi, se questa linea è alta, allora faccio qualcosa con alcune altre linee".

Per facilitare ciò, queste linee sono raggruppate insieme. Alcuni sono usati per indirizzare i dispositivi, alcuni sono usati per trasferire dati per quegli indirizzi e altri ancora sono solo "Amico, c'è qualcosa di importante nel mio chip".

Alla fine, la tua CPU dice semplicemente a qualche altro chip di modificare il segnale sul monitor in modo che assomigli a "Hello World".

Google disegna un display a 7 segmenti. Ha dei fili, che faranno illuminare un segmento se si applica tensione ad esso. Se si collega ora una linea di uscita della CPU con una linea del display a 7 segmenti, il display si illumina. Non è la CPU che fa accendere il LED, applica solo tensione alle linee, ma alcune altre cose hardware potrebbero fare cose carine a causa sua.

Se la tua CPU ora imposta tutte le linee per H su alto, il 7 segmenti visualizzerà H, sebbene H non sia un numero che una CPU aggiungerebbe o sottrarrebbe.

Ora, se tutti i livelli concordano ciò che è necessario per rendere il display a 7 segmenti H (impostare 5 righe specifiche su alto), il compilatore Java può creare il codice per farlo visualizzare H. Questo è ovviamente piuttosto scomodo - quindi i livelli iniziano astrarre. Il livello più basso inizierà con: "Yo, ci sono 26 lettere, assegniamo i numeri a ciascuna lettera - che ne dici di dare alla lettera 'H' il numero '72'? Quindi puoi dirmi" Mostra lettera 72 ", invece di "Imposta la linea 309 alta, imposta la linea 310 alta, imposta la linea 498 alta, imposta la linea 549 alta, imposta la linea 3 alta". E così ogni strato inizia ad astrarre informazioni, come ottenere determinati risultati, quindi non è necessario prendersi cura di loro.

Quindi sì, si riassume in un'enorme mappatura di numeri o bit, che la CPU può effettivamente elaborare, ai significati concordati da tutti nella catena.


3

Al college come parte di un programma di laurea in CS, ho studiato un esempio esteso di linguaggio di trasferimento dei registri che definisce una CPU. Sono stato ispirato a prendere una diversa opinione su di esso e scrivere un simulatore che accetta tale notazione come una definizione, e ho pubblicato quello in Embedded Systems Programming (numero di marzo 1989) come un modo per rispondere allo stesso tipo di domanda che hai posto, consentendo alle persone di costruire la loro comprensione intuitiva di tali cose.

In classe, abbiamo continuato a distillare quella notazione di trasferimento dei registri in porte logiche reali sui registri! Scrive se stesso: guarda tutto ciò che ha il registro 'A' come destinazione e il codice A = (case1) o (case2) ... e che viene espresso come forma normalizzata di somma dei prodotti o del prodotto delle somme.

Solo alla fine del corso ho appreso che questa era una vera CPU: il PDP-8 se ricordo bene.

Oggi è possibile alimentare lo schema del gate in un chip di array logico programmabile.

Questo è l'essenza: un registro è impostato con il risultato delle porte AND e OR che riportano ad altri registri. Uno dei valori da includere è il valore del codice operativo.

Quindi immagina: A: = (opcode == 17 & X + Y) | (opcode == 18 & X + Z) | ...

I moderni cpus sono più complicati, con condutture e bus, ma le singole subunità come una singola ALU funzionano in questo modo.


2

Stai considerando la CPU qui, ma c'è un altro componente coinvolto quando si esegue "Hello World": il display!

Per la CPU, un valore in memoria è solo un numero rappresentato come un dato numero di bit (0 e 1).

Come si trasforma in lettere sullo schermo è un'altra storia: il display ha anche memoria. Questa memoria (memoria grafica) è mappata su "pixel" sullo schermo. Ogni pixel è codificato con un valore: se è un display monocromatico molto semplice, il valore è solo intensità, per i display a colori il valore è una combinazione di rosso verde e blu (RGB) che può essere codificato in molti modi diversi.

Pertanto, quando la CPU "scrive" un determinato valore nella memoria del display, i pixel si illuminano. Per scrivere effettivamente lettere, è necessario illuminare molti pixel. In genere un computer avrà un set di caratteri (in realtà diversi) definito nel suo sistema operativo. (facendo astrazione dei 'caratteri' stessi, che si associa a una definizione di come ogni lettera dovrebbe apparire sullo schermo)

Quindi, man mano che il codice viene compilato, include tutti i tipi di cose che provengono dalle librerie del sistema operativo, inclusi questi set di caratteri / caratteri ecc. Che consentono alla CPU di sapere cosa scrivere dove si trova nella memoria grafica. (È piuttosto complesso ma questa è l'idea generale: il compilatore include molto più codice di quello che c'è solo nel tuo codice "ciao mondo", attraverso le librerie importate)

Alla fine, ci sono state molte cose che accadono mentre sospetti, ma non hai dovuto scrivere tutto quel codice.


1

Ecco un approccio formale alla tua domanda nel campo dell'informatica teorica.

Fondamentalmente, possiamo definire una mappatura tra il modello di calcolo di una CPU e una macchina di turing. Esistono prove teoriche che l'insieme di tutti i programmi immaginabili di macchine per turing (e quindi di tutti i programmi immaginabili eseguibili su una CPU) sia numerabile infinito. Ciò significa che possiamo identificare ogni programma con un numero naturale univoco, incluso il programma che estenderebbe i numeri naturali alle macchine di turing .

Poiché già sai che quasi tutto ciò che fanno le CPU sono calcoli su numeri naturali nella rappresentazione binaria, puoi ragionare che le CPU possono eseguire ogni programma immaginabile.

Nota: questo è eccessivamente semplificato, ma, a mio avviso, dà una buona intuizione.


1

Ciò che può aiutare è spostare il tuo pensiero lontano dal "fare l'aritmetica". Se stai davvero cercando di capire cosa fanno i computer sotto il cofano per stampare "Hello World", è meglio pensare a un livello inferiore. Lo "stato" del computer può essere descritto come un insieme di bit, memorizzati da interruttori a transistor che sono accesi o spenti (o condensatori che sono caricati o non caricati). Il computer manipola quei bit secondo le regole. I modi in cui al computer è consentito manipolare quei bit sono scritti sulla CPU sotto forma di transistor che svolgono il compito di cambiare i bit da 0 a 1 o da 1 a 0.

Quando un ALU "fa l'aritmetica", ciò che realmente significa è che ha cambiato lo stato del computer in modo coerente con le nostre regole di aritmetica. Tutto ciò che ha fatto è stato cambiare alcuni bit. È il significato dietro il software che spiega perché dovremmo pensarlo come addizione o sottrazione. La CPU non "sa" cosa sta facendo. Cambia solo da stato a stato, e questo è tutto (almeno fino a quando Skynet non subentra).

Se la pensi in questo modo, le istruzioni più complicate come un'istruzione "jump" non sono diverse. Tutto ciò che fa è cambiare alcuni bit. In questo caso capita di cambiare i bit che sappiamo significano la posizione della prossima istruzione da eseguire. La CPU non "lo sa", ma noi lo sappiamo. Quindi usiamo le istruzioni che cambiano quei bit per "saltare" da un posto all'altro nel nostro codice.

Anche l'IO non è diverso, sta solo cambiando i bit. L'unica differenza minore è che quei bit sono collegati ai transistor che alla fine portano a illuminare i caratteri sullo schermo. Se potessi tornare indietro di qualche decennio a quando "Hello World" era in realtà semplice, c'era uno spazio di memoria in cui, se scrivessi bit corrispondenti ai caratteri ASCII per "Hello World", quei personaggi sarebbero resi direttamente al schermo. Al giorno d'oggi è un po 'più complicato, perché abbiamo schede grafiche e sistemi operativi che lo rovinano, ma l'idea di base è la stessa. Hai una serie di transistor che sono accesi o spenti, che sono collegati ai circuiti per visualizzare un pixel sullo schermo. Abbiamo impostato quelli giusti e sembra che "Hello World" appaia sullo schermo.

La confusione è semplicemente una questione di sintassi vs semantica. Il comportamento di una "metà aggiunta" o di una "aggiunta completa" in una ALU è sintassi. Definisce quali bit verranno emessi quando si inseriscono bit. La semantica di esso è il concetto della capacità di fare l'addizione. Tu e io siamo consapevoli che l'ALU può "fare l'aggiunta", ma per capire veramente cosa succede sotto, devi ricordare che un ALU manipola solo i bit e i byte della sintassi.


0

Le CPU funzionano così:

  • recupera istruzione corrente, incrementa il puntatore "istruzione corrente".

  • decodificalo (es. scopri cosa dicono queste istruzioni alla CPU)

  • eseguilo (fai quello che dice l'istruzione) - il puntatore dell'istruzione corrente può essere modificato se l'istruzione è qualcosa come un "salto".

  • Ripeti per sempre

Le CPU moderne sono più complesse e provano a sovrapporsi pesantemente e persino a prevedere parti di quel processo (ad es. Iniziare l'esecuzione mentre altre 10 istruzioni stanno decodificando mentre la CPU sta andando molto avanti rispetto al puntatore "istruzione corrente" per mantenere piene le "pipeline"), ma il processo essenziale è davvero lo stesso.

Esistono molti tipi di istruzioni, un esempio della maggior parte di essi è:

  • Istruzioni "Sposta". Questi possono copiare X su un'altra X, dove X è memoria (RAM), un registro o un indirizzo nello spazio I / O se la CPU supporta tale nozione.

  • Istruzioni per la manipolazione dello stack, incluso pop in register, push register on stack, ecc. Questi sono casi particolari di istruzioni "move" che usano e aggiornano un registro "stack pointer".

  • Istruzioni che eseguono operazioni matematiche, tra due registri o memorie e un registro. Queste istruzioni riguardano automaticamente un registro delle bandiere. Uno di questi flag è il flag "zero" che viene impostato se il risultato è zero, un altro è il flag "negativo" che viene impostato se viene impostato il bit più significativo del risultato. Potrebbero essercene altri a seconda della CPU.

  • Un caso speciale di operazioni matematiche sono le istruzioni di confronto, che è lo stesso di una sottrazione, ma il risultato non viene mantenuto. Le bandiere sono ancora interessate.

  • Esistono istruzioni di diramazione che passano a un indirizzo di memoria SE sono impostati flag specifici. Ricorda la bandiera "zero" di cui sopra? Raddoppia anche come flag "se uguale", quindi vedi istruzioni come BEQsu molte CPU che in realtà si ramifica se è impostato il flag "zero".

  • Istruzioni che eseguono operazioni logiche (AND, OR, NOT), bit di spostamento e bit di prova. Possono influire su flag come le istruzioni matematiche a seconda della CPU.

  • Istruzioni che saltano incondizionatamente.

  • Istruzioni che saltano e salvano l'indirizzo di ritorno nello stack (una "chiamata") e altre istruzioni che fanno scattare un indirizzo dallo stack (un "ritorno").

  • Istruzioni speciali come quelle che arrestano la CPU, identificano la CPU o richiamano i gestori di interrupt.

  • "Nessuna operazione": quasi tutte le CPU hanno un'istruzione "no-op" che consuma solo cicli e va avanti.

Questo è solo un esempio, ci sono CPU con meno tipi di istruzioni e CPU con più.

Il punto è illustrare che ci sono molti tipi di istruzioni oltre alle istruzioni matematiche in una CPU. Tutto in un linguaggio di livello superiore è suddiviso per i tipi di operazioni sopra e solo alcuni di questi saranno istruzioni matematiche o di tipo ALU.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.