Numero minimo teorico di registri per un computer moderno?


10

Ho seguito un corso sui compilatori nei miei studi universitari in cui abbiamo scritto un compilatore che compila i programmi sorgente in un linguaggio simile a Java giocattolo in un linguaggio di assemblaggio giocattolo (per il quale avevamo un interprete). Nel progetto abbiamo formulato alcune ipotesi sulla macchina target strettamente correlate a eseguibili nativi "reali", tra cui:

  • uno stack di runtime, seguito da un registro puntatore dello stack dedicato ("SP")
  • un heap per l'allocazione dinamica degli oggetti, monitorato da un registro del puntatore heap ("HP") dedicato
  • un registro contatore programmi dedicato ("PC")
  • la macchina target ha 16 registri
  • le operazioni sui dati (al contrario, ad esempio, i salti) sono operazioni da registro a registro

Quando siamo arrivati ​​all'unità utilizzando l'allocazione dei registri come ottimizzazione, mi sono chiesto: qual è il numero minimo teorico di registri per tale macchina? Dai nostri presupposti si può vedere che nel nostro compilatore sono stati utilizzati cinque registri (SP, HP, PC, più due da utilizzare come memoria per operazioni binarie). Mentre le ottimizzazioni come l'allocazione dei registri possono certamente fare uso di più registri, c'è un modo per cavarsela con meno mantenendo le strutture come stack e heap? Suppongo che con l'indirizzamento dei registri (operazioni da registro a registro) siano necessari almeno due registri, ma ne abbiamo bisogno più di due?


Un "puntatore di heap" sembra un'idea strana. Perché contrariamente allo stack, l'heap non è LIFO e non si riduce alla semantica push / pop. Dovresti piuttosto vedere l'allocazione dinamica della memoria come chiamate a routine malloc / libere.
Yves Daoust,

Risposte:


14

Se si consente l'accesso diretto alla memoria tramite l'indirizzo di memoria, non è necessario alcun "registro" perché è possibile utilizzare le posizioni di memoria. Ad esempio, la memoria nella posizione 0 può essere il contatore del programma, nella posizione 1 abbiamo il puntatore dello stack, ecc. Ma questo è barare.

Quindi, per evitare di barare, supponiamo che non ci sia accesso diretto alla memoria, perché potremmo usare posizioni di memoria fisse come registri. Quindi possiamo cavarcela con due registri, un contatore di programmi e un puntatore dello stack, come spiegato nell'articolo di Wikipedia sulle macchine dello stack . Lo stack è accessibile solo tramite il puntatore dello stack e il programma è accessibile solo tramite il contatore del programma.

Un'altra possibilità è quella di utilizzare macchine da banco. Una macchina a due contatori è Turing completa, cioè può calcolare qualunque macchina Turing. Questo di nuovo è ben spiegato nell'articolo di Wikipedia sulle macchine da banco .


Grazie per la risposta! L'articolo sulle macchine stack menziona, tuttavia, che la macchina è in grado di accedere direttamente alla memoria (per eseguire operazioni sugli elementi dello stack più in alto e rimandare il risultato), quindi è ancora barare, giusto? Per quanto riguarda il bancone, ho letto quell'articolo. Ho anche letto una prova simile di TC di un 2-CM, ma entrambi implicano effettivamente l'archiviazione di tutta la RAM in due registri, il che mi sembra ancora più un imbroglio.
BlueBomber,

Bene, ad un certo punto non sta più barando. Le operazioni dello stack non stanno imbrogliando, purché non consentano l'accesso diretto a una posizione fissa in memoria. Va bene essere in grado, per esempio, di ruotare i tre elementi più in alto della pila. La tua domanda è un po 'strana, comunque, quindi non paga per essere ossessionato da ciò che è e non sta tradendo.
Andrej Bauer,

Grazie ancora per la risposta. Ogni volta che l'argomento si riferisce a limiti teorici, barare è ancora meno accettabile! Ciò non significa che non sia istruttivo, però. Il punto in cui non è barare è quando, beh, non c'è barare, immagino. Ho trovato la tua risposta iniziale informativa, ma il problema è che il nostro modello si sovrappone a tutti i modelli di Turing Machine, Counter Machine e Stack Machine, e dati i nostri presupposti (inclusi finitamente molti registri finiti e nessun accesso diretto alla memoria), possiamo ottenere con solo due registri?
BlueBomber,

1
Trovo la domanda strana perché è difficile individuare concetti del mondo reale come processore, registro, accesso alla memoria, ecc., Ma è necessario che siano bloccati per poter provare qualsiasi cosa. Quindi il risultato finale sarà che qualsiasi cosa tu dimostri è facile da dimostrare, ma dipende molto da come formalizzi la domanda (qual è la tua nozione teorica di "processore", "registro", "memoria", ecc.).
Andrej Bauer,

1
Un libro di testo del compilatore non ci consente di dimostrare molto, almeno non nel senso matematico della parola "prova". È necessario fare un ulteriore passo avanti nella formalizzazione dell'hardware per arrivare a qualcosa che consentirà la prova . Ad ogni modo, stiamo dividendo i capelli e ti ho già dato la mia migliore risposta.
Andrej Bauer,

1

L'architettura PIC, introdotta da General Instruments negli anni '70 ed è ancora in uso oggi, aveva i seguenti registri:

W register (not addressible)
01    Timer/Counter
02    Program Counter
03    Status
04    File-Select Register
05-07 One register for each I/O port
08-1F General-purpose registers/"memory"

Un'istruzione tipica leggerà un registro, eseguirà un calcolo usando il valore letto e W, quindi memorizzerà il risultato del calcolo su W o sul registro letto. Uno dei calcoli disponibili produce "il valore letto, ignorando W"; un altro è "prendi W, ignorando il valore letto". I pattern di bit che corrisponderebbero a "leggi XX, quindi prendono W, ignorando il valore letto e memorizzano il risultato in W" sono usati per NOP e per una varietà di istruzioni speciali.

Per consentire i calcoli degli indirizzi, l'unità di esecuzione del processore controllerà le istruzioni che codificano un indirizzo di 00 e sostituirà il contenuto del registro di selezione file per l'indirizzo.

Sebbene dover inserire tutti i valori attraverso il registro W possa essere un collo di bottiglia, l'architettura PIC ha un set di lavoro più ampio rispetto ad altre architetture che usano la stessa parola di istruzioni di lunghezza. Sul PIC16C54 (ancora fatto oggi e molto simile ai PIC degli anni '70) le istruzioni sono lunghe 12 bit. Su molte altre parti 16Cxx o 16Fxx, le istruzioni sono lunghe 14 bit e possono accedere direttamente a uno spazio di indirizzi a 128 byte. Se il working set di un programma si adatta bene al working set del set di istruzioni, un'istruzione come "total + = value", in cui "total" e "value" sono di tipo unsigned char, si compila in:

movf  value,w
addwf total,f

Su qualcosa come ARM, anche se si ha un registro precaricato con l'indirizzo base delle proprie variabili, il codice sarebbe più simile a:

ldr    r0,[r7+value]
ldr    r1,[r7+total]
add    r1,r1,r0
str    r1,[r7+total]

In molti casi, un compilatore sarebbe in grado di evitare di caricare e archiviare ogni operazione, ma su qualcosa come il PIC, i vantaggi di un set di lavoro più ampio possono talvolta superare i limiti di dover passare sempre attraverso W.

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.