Vai al contenuto
Il server del mese è
Visita la nostra nuova lista server!

Archiviato

Questa discussione è archiviata e chiusa a future risposte.

N1xx1

Dcpu Tutorial

Recommended Posts

DCPU-16 Tutorial

Struttura di una CPU

Una CPU (fisica o virtuale non ha importanza) è una macchina di calcolo dotata di una tabella di registri e un insieme di operazioni.

I registri sono celle di memoria che contengono un numero.

La DCPU è una macchina a 16 bit quindi i registri sono grandi 16 bit e perciò possono contenere 65536 combinazioni ciascuno.

Esistono alcuni registri speciali:

Program Counter: PC

<p>Un registro fondamentale è il Program Counter o PC.

</p><p> Il PC tiene traccia delle istruzioni, in particolare segnala su quale istruzione ci si trova.

Una volta eseguita un'operazione il PC viene incrementato di 1 (ossia si passa alla riga successiva).</p>

Stack Pointer: SP

Lo Stack è un struttura (se sia un registro o altro non ha importanza) dotata delle operazioni di PUSH, ,POP e PEEK.

Fare una PUSH significa inserire un valore sulla cima dello STACK.

Fare una POP significa estrarre dalla cima dello STACK.

Fare una PEEK significa leggere il valore sulla cima dello STACK senza estrarlo.

Lo stack è gestito tramite il registro speciale SP.

Lo STACK si dice "LIFO": Last In First Out. Ossia l'ultimo che entra è il primo ad uscire (come un mazzo di carte).

Programmare la CPU

Una CPU è in grado di decifrare a livello hardware solo numeri. Il codice macchina, perciò, è composto da soli numeri.

L'asseemblatore traduce l'assembly (il linguaggio che andremo a spiegare) in numeri che la macchina può capire.

Non è assolutamente importante sapere a quale numero corrisponde un comando.

Sistema di numerazione: binario, esadecimale.

Cos'è un sistema di numerazione? È il modo in cui si scrivono i numeri.

I romani usavano un sistema di numerazione molto diverso dal nostro.. ma non è il caso di partire da lì, giusto?

Quello che vi basta sapere è che noi usiamo un sistemadi numerazione posizionale decimale (cioè abbiamo 10 cifre).

I computer usano lo stesso sistema, ma binario (hanno solo 0 e 1; scomodo? Grazie a questo sistema puoi contare fino a 1023 con le dita!), è molto comodo usare la base 16 (anche per contare fino a f, fa un sacco figo).

Non è importante che voi sappiate trasformare i numeri da una base all'altra.. perchè tanto c'è google.

Da decimale a binario: https://www.google.c...?q=10+to+binary

Da binario a decimale: https://www.google.c...0b10+to+decimal

Da decimale a esadecimale: https://www.google.c...rch?q=10+to+hex

Da esadecimale a decimale: https://www.google.c...0x10+to+decimal

Nella DCPU per specificare se un numero è in base 16 (cioè esadecimale) basta specificare

0x

davanti al numero.

Quindi 0x0010 vale... mentre 10 vale.... (Risposta: 1610 e 1010. 10: Significa in base 10).

L'Esadecimale è un sistema di numerazione a 16 cifre: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E e F.

È utile per scrivere visto che il nostro è un sistema a 16 bit.

Operazioni bitwise

Le operazioni bitwise sono le operazioni tra bit.

Le fondamentali sono:

a AND b :

AND logico tra i bit dei due numeri. I bit diversi diventano 0, quelli uguali restano inalterati.

0111001 &amp;
0011101 =
0011001

a OR b : Or logico tra i bit dei due numeri. I bit diversi diventano 1, gli altri rimangono invariati.

0111001 |
0011101 =
0111101

a XOR b : Xor logico tra i bit dei due numeri. I bit diversi diventano 1, quelli uguali diventano 0.

0111001 ^
0011101 =
0100100

NOT a : Not logico di un numero. Si invertono i bit.

0111001 !
1000110

a SHR b : shift destro dei bit di a di b posizioni. (Equivale a dividere per 2 alla b )

0111001 &gt;&gt; 2
0001110

a SHL b : shift sinistro dei bit di a di b posizioni. Uguale a prima ma verso sinistra. (Equivale a moltiplicare per due alla b )

Come scrivere per DCPU

Elementi fondamentali

Registri

Oltre ai fondamentali PC e SP in DCPU abbiamo 8 registri: A, B, C, X, Y, Z, I e J.

Per utilizzare i registri si usa la loro lettera corrispondente.

Un altro registro è O, chiamato registro di overflow. Ci serve per capire se abbiamo commesso errori (o in generale, se l'operazione non è andata a buon fine).

LA DCPU dispone di una memoria con 128Kb celle (dette parole).

Ognuna di queste celle è numerata da 0x0000 a 0xffff.

Il numero della cella ne rappresenta il nome (come A,B.. per i registri).

Ma a differenza dei registri il nome non basta per accedere il contenuto di una cella di memoria infatti per ottenere il contenuto di una cella è necessario metterne tra quadre il nome, ad esempio [0x1000] è il contenuto della cella di nome 0x1000.

Inizialmente le celle si possono considerare vuote ma è buona norma considerare il contenuto iniziale "sporco", cioè casuale.

Istruzioni base

a: registro o memoria indicizzata [x]

b: numero (registro, memoria indicizzata o numero)

SET a, b : assegna ad a il valore di b

ADD a, b : assegna ad a il risultato di a + b

SUB a, b : assegna ad a il risultato di a - b

MUL a, b : assegna ad a il risultato di a * b

DIV a, b : assegna ad a il risultato di a / b

MOD a, b : assegna ad a il risultato di a % b (resto della divisione)

SHR a, b : assegna ad a il risultato di a >> b

SHL a, b : assegna ad a il risultato di a << b

AND a, b : assegna ad a il risultato di a & b

BOR a, b : assegna ad a il risultato di a | b

XOR a, b : assegna ad a il risultato di a ^ b

IFE a, b : esegue la prossima istruzione se a = b

IFN a, b : esegue la prossima istruzione se a != b (diverso)

IFG a, b : esegue la prossima istruzione se a > b

IFB a, b : esegue la prossima istruzionr se (a & b ) != 0 (hanno almeno un bit 1 in comune)

Errore (Overflow) nelle operazioni

Una CPU non può dividere per zero (solo Chuk Norris può) o sommare oltre i limiti dei suoi bit.

Per sapere se abbiamo fatto i cattivi, quando un'operazione va in overflow un registro O viene modificato.

Nella somma, se va in overflow setta O su 0x0001, altrimenti su 0x0.

Nella sottrazione, se va in underflow setta O su 0xFFFF, altrimenti su 0x0

Nella moltiplicazione, setta O su ((a*b )>>16)&0xffff

Nella divisione, setta O su ((a<<16)/b )&0xffff, se il divisore è 0 setta O su 0x0.

Nello shift sinistro, setta O su ((a<<b )="">>16)&0xffff

Nello shift destro, setta O su ((a<<16)>>b )&0xffff</b>

Come stampare in output

Il sistema di Output non è ancora stato ufficializzato da Notch.

Fondamentalmente non sappiamo ancora quali saranno le componenti che potranno essere utilizzate dalla CPU.

In questa guida prenderemo come riferimento il sito http://x10co.de

Il terminale è "indicizzato" da alcune celle particolari di memoria.

In particolare, la cella di memoria 0x8000 rappresenta lo spazio sul terminale sulla prima riga e la prima colonna.

Si va avanti per righe, quindi 0x8001 è lo spazio sulla prima riga e la seconda colonna.

Ogni riga ha 32 colonne, quindi si arriva a 0x801f.

0x8020 è il primo spazio sulla seconda riga.

Siccome vogliamo scrivere su uno spazio di memoria, per scrivere in output dovremo scrivere

SET [0x8000], A

Con A che contiene il CARATTERE da stampare.

Caratteri

Il sistema 0x10co.de prevede l'utilizzo dell'ASCII per stampare a video. L'ASCII è una vecchia (ma ancora utilizzata) codifica dei caratteri. Ad ogni carattere è associato un numero. E per stampare un certo carattere dovreste stampare il numero corrispondente.

La tabella ASCII è consultabile http://it.wikipedia.org/wiki/ASCII . Noi saremo interessati alla colonna HEX.

Dalla tabella è possibile vedere che a 'c' corrisponde 0x0063 . Mentre a 'F' corrisponde 0x0046 , ecc.

Per stampare 'c''i''a''o' dovremo scrivere


SET [0x8000], 0x0063
SET [0x8001], 0x0069
SET [0x8002], 0x0061
SET [0x8003], 0x006f
BRK; serve per interrompere la computazione
[/CODE]

Ma se provate a usare questo codice otterrete uno schermo nero!

Perchè?

L'output di 0x10co.de è fatto in modo che oltre al carattere è importante specificare il colore del carattere e lo sfondo.

Questi due colori sono dati dalle prime due cifre del numero corrispondente alla cifra.

0x0061 è una 'a' nera (0) su sfondo nero (0)

0xf061 è una 'a' bianca (f) su sfondo nero (0)

0x0f61 è una 'a' nera(0) su sfondo bianco.

Per scrivere correttamente ciao dovremo quindi scrivere:

[CODE]
SET [0x8000], 0xf063
SET [0x8001], 0xf069
SET [0x8002], 0xf061
SET [0x8003], 0xf06f
BRK; serve per interrompere la computazione
[/CODE]

[b]Esercizi[/b]

[b]Esercizio 1: [/b][i]Stampare il contenuto dei registri A,B,C,I in colonna.[/i]

[CODE]
SET [0x8000],A
SET [0x8020], B
SET [0x8040],C
SET [0x8060],I
BRK; server per interrompere la computazione
[/CODE]

[b]Esercizio 2:[/b] [i]Stampare 1 se A è uguale a 0 altrimenti stampare 0.[/i]

Soluzione 1:

[CODE]SET A,1; esempio.
SET B, 0xf030
IFE A,0
ADD B,1
SET [0x8000],B
BRK[/CODE]

Soluzione 2:

[CODE]SET A,0; esempio
IFE A,0
SET [0x8000],0xf031
IFG A,0
SET [0x8000],0xf030
BRK[/CODE]

Soluzione 3:

[CODE]SET A,1
SET B,1
XOR B,A
ADD B,0xf030
SET [0x8000], B
BRK[/CODE]

[b]Esercizio 3: [/b][i]Stampare tante 'A' quanto il valore di B, una dopo l'altra.[/i]

[CODE]SET C,1
:START
IFE C,B
SET PC, END
SET [0x7fff+C], 0xf041; per evitare che parta dal secondo spazio uso 7fff e sommo 1.
;o in alternativa
;SET I, 0x7fff
;ADD I,C
;SET [I],0f041
ADD C,1
SET PC, START
:END
BRK[/CODE]

[b]Esercizio 4: [/b]Creare un programma che stampi A all'infinito!

Versione 1:

[CODE]
SET A, 0xf041
:LOOP
SET [0x8000],A
SET PC,LOOP
[/CODE]

Ma così SEMBRA che non succeda nulla...

Versione 2:

[CODE]SET A, 0x0041;imposto il carattere

SET C, 0x8000;output

SET B,0;puntatore alla posizione

SET X, 0xf000;colore della A
:LOOP
SET Z,A
BOR Z,X;aggiungo un colore alla A
SET I,C
ADD I,B;posiziono l'output
SET [I],Z
ADD B,1
MOD B,31;avanzo con la posizione ma non vado oltre il 30...
ADD X,0x1000;avanzo con il colore

SET PC, LOOP;see the result![/CODE]

[b]Esercizio 5: [/b]Creare un programma che stampa una cifra salvata in A (A vale da 0 a 9):

Indizio: usare l'ascii e il valore ascii di 0.

[CODE]
SET A,8;esempio
ADD A, 0x0030; valore ascii di '0'
ADD A, 0xf000; colore
SET [0x8000],A

[/CODE]

[size=5][b]Sistema di Input[/b][/size]

Il sistema di input non è ancora stato ufficializzato da Notch e come nelll'output...

(continua)

Condividi questo messaggio


Link di questo messaggio
Condividi su altri siti

L'unica cosa che non comprendo sono i valori...

Esattamente, il valore 0 o il valore 1 a cosa corrisponde esattamante?

La parte dei codici mi sembra di essere a 50% ma il resto... (scusate sono una schiappa in questa materia)

Ad esempio, come si capisce che ":set A, 0 = Una parola, testo , ecc"?

Mi sembra strano. comunque aspetterò domani per le risposte :)

P.S. Adesso il Titanic sta affondando...

Condividi questo messaggio


Link di questo messaggio
Condividi su altri siti

L'unica cosa che non comprendo sono i valori...

Esattamente, il valore 0 o il valore 1 a cosa corrisponde esattamante?

La parte dei codici mi sembra di essere a 50% ma il resto... (scusate sono una schiappa in questa materia)

Ad esempio, come si capisce che ":set A, 0 = Una parola, testo , ecc"?

Mi sembra strano. comunque aspetterò domani per le risposte :)

P.S. Adesso il Titanic sta affondando...

Non ho capito la domanda..

Condividi questo messaggio


Link di questo messaggio
Condividi su altri siti

Messo la roba di fabio e messo qualcosa sui registri. Mi manca il registro di overflow, poi ne parlo a parte.

Condividi questo messaggio


Link di questo messaggio
Condividi su altri siti

Cavolo e dire che sta roba qui l'ho tutta studiata e avevo anche 10 su z80.

Devo ridarci una spolverata.

Condividi questo messaggio


Link di questo messaggio
Condividi su altri siti

Uhm... guida molto utile, ma non riesco a capire come fare a stampare a "schermo" le cose...

Condividi questo messaggio


Link di questo messaggio
Condividi su altri siti

Uhm... guida molto utile, ma non riesco a capire come fare a stampare a "schermo" le cose...

Semplicissimo.

Basta operare con la ram. Gli indirizzi da 0x8000 a 0x81FF corrispondono ognuno a un carattere nello schermo (in 0x10co.de vanno da 0x800 a 0x817F). Per stampare un carattere devi assegnare alla posizione una cosa del tipo:

hrgb hrgb h ccccccc

Dove il primo hrgb è il colore del carattere, il secondo hrgb è il colore dello sfondo, h è se il carattere deve lampeggiare e c è il valore ascii del carattere.

Per esempio:

SET [0x8000], 0xF030

Stamperà uno zero bianco su sfondo nero alla posizione 0.

Condividi questo messaggio


Link di questo messaggio
Condividi su altri siti

Notare che l'input/output funziona solo in quel sito. Notch non ha ancora dato modo di farlo.

(Aspetto una risposta di Guru)

Condividi questo messaggio


Link di questo messaggio
Condividi su altri siti

Oddio che casino... Secondo me notch cercherà di fare qualcosa di più semplice, in modo da dare la possibilità di giocare anche all'utenza che non ha tempo e/o voglia di studiare assembly

Condividi questo messaggio


Link di questo messaggio
Condividi su altri siti

Ma come faccio a verificare sullo schermo nero del sito 0x10c.de che l'operazione che ho scritto è avvenuta? Cioè, come faccio a vedere l'output? E anche ad immettere un input già che ci siamo xD (se non mi sono spiegato bene, intendo le corrispondenti funzioni di printf e scanf del C)

Condividi questo messaggio


Link di questo messaggio
Condividi su altri siti

Ma come faccio a verificare sullo schermo nero del sito 0x10c.de che l'operazione che ho scritto è avvenuta? Cioè, come faccio a vedere l'output? E anche ad immettere un input già che ci siamo xD (se non mi sono spiegato bene, intendo le corrispondenti funzioni di printf e scanf del C)

Devi modificare [0x8000] in avanti andando a scrivere tipo 0xF030

Cioè, come ha detto nuno:

Set [0x8000], 0xf030 scrive uno zero sul terminale in prima posizione. Ciao

Condividi questo messaggio


Link di questo messaggio
Condividi su altri siti

Devi modificare [0x8000] in avanti andando a scrivere tipo 0xF030

Cioè, come ha detto nuno:

Set [0x8000], 0xf030 scrive uno zero sul terminale in prima posizione. Ciao

Ok mille grazie (è già un passo in avanti ^_^). Hai idea di dove posso trovare i codici (o come ricavarli) di tutti i simboli? Cioè, ho notato che ad esempio set [0x8000],0xf4f2 da come output un rettangolino rosso

Condividi questo messaggio


Link di questo messaggio
Condividi su altri siti

Ok! Sono riuscito a stampare una a minuscola scrivendo set [0x8000], 0xf61 solo che c'è un problema: viene fuori la 'a' nera su un quadratino bianco. Ora, ho pensato che dovessi togliere la f prima di 61, ma se la tolgo non appare nulla xD Scusami la niubbaggine.

Edit. non so se si è capito, ma io voglio togliere il rettangolino di sfondo e cambiare colore alla lettera xD

Condividi questo messaggio


Link di questo messaggio
Condividi su altri siti

Altro mega dubbio, come faccio a far apparire il risultato di una somma?

Cioè: scrivo

set a,0

add a,5

come faccio a far apparire il nuovo valore di a sullo schermo???

Condividi questo messaggio


Link di questo messaggio
Condividi su altri siti

Ok! Sono riuscito a stampare una a minuscola scrivendo set [0x8000], 0xf61 solo che c'è un problema: viene fuori la 'a' nera su un quadratino bianco. Ora, ho pensato che dovessi togliere la f prima di 61, ma se la tolgo non appare nulla xD Scusami la niubbaggine.

Edit. non so se si è capito, ma io voglio togliere il rettangolino di sfondo e cambiare colore alla lettera xD

Ti sei dimenticato lo 0. 0xf061

se scrivi solo f è come se fosse 0x0f61

Altro mega dubbio, come faccio a far apparire il risultato di una somma?

Cioè: scrivo

set a,0

add a,5

come faccio a far apparire il nuovo valore di a sullo schermo???

set A,0

set [0x8000], A

add A, 5

set [0x8000], A

Nota che in questo modo non scrivi 0 ma il carattere corrispondente a 0 (che non è quello che vuoi).

Per stampare 0 puoi fare

set A, 0xf030

set [0x8000], A

add A, 5

set [0x8001], A

e guarda un po' cosa viene fuori..

Condividi questo messaggio


Link di questo messaggio
Condividi su altri siti

eh già, devo esser l'unico che non ha capito niente...

Credevo di aver capito, ma invece no, quindi non sei solo :asd:

Condividi questo messaggio


Link di questo messaggio
Condividi su altri siti

Ti sei dimenticato lo 0. 0xf061

se scrivi solo f è come se fosse 0x0f61

set A,0

set [0x8000], A

add A, 5

set [0x8000], A

Nota che in questo modo non scrivi 0 ma il carattere corrispondente a 0 (che non è quello che vuoi).

Per stampare 0 puoi fare

set A, 0xf030

set [0x8000], A

add A, 5

set [0x8001], A

e guarda un po' cosa viene fuori..

Allora, ok grazie per il rettangolino (stavo per impazzire xD)

Invece per la seconda parte non capisco perché l'add non funge, cioè, non fa una somma:

Ecco il codice:

set A, 0xf031 ; A=1

set [0x8000], A ;Output A

add A, 0xf035 ;tecnicamente dovrebbe essere 1+5

set [0x8001], A ;Output A dopo 1+5

Cioè, da quello che ho capito, la A dopo l'add dovrebbe essere diventata 6, invece è 5, come mai???

Condividi questo messaggio


Link di questo messaggio
Condividi su altri siti

Allora, ok grazie per il rettangolino (stavo per impazzire xD)

Invece per la seconda parte non capisco perché l'add non funge, cioè, non fa una somma:

Ecco il codice:

set A, 0xf031 ; A=1

set [0x8000], A ;Output A

add A, 0xf035 ;tecnicamente dovrebbe essere 1+5

set [0x8001], A ;Output A dopo 1+5

Cioè, da quello che ho capito, la A dopo l'add dovrebbe essere diventata 6, invece è 5, come mai???

Forse sono io che ti ho confuso.

Un conto è il numero. Un conto è il carattere che stampi.

0 è 0x0030 (colore a parte)

5 è 0x0035

Ma quelli sono i caratteri!

Tu stai facendo '0'+'5' non 0+5.

Quello che puoi fare è calcolarti il numero

SET A,0

ADD A,5

Ora A vale 5.

Come fai a stampare un numero?

Esempio generale: prendi B e lo setti al carattere 0

SET B,0xf030

Ora se sai che A è minore di 10 basta fare

ADD B,A

SET [0x8000], B

e sei a posto

Se A è maggiore di 10.. ma minore di 100

SET A, 0x000f;

SET C, A ; mi salvo il numero

DIV C, 10; divido per 10 (es. 94 /10 = 9)

;ora C contiene la prima cifra

MOD A, 10; prendo il resto della divisione (94 mod 10 = 4)

;ora A contiene la seconda cifra

;ora ho le singole cifre devo trasformarli in caratteri

SET B,0xf030

ADD C,B

ADD A,B

SET [0x8000],C

SET [0x8001],A

Per un numero generico non è molto più complicato basta fare i diversi casi usando ifg.. prova a faro tu :) (nota che al massimo si arriva a 65536)

Condividi questo messaggio


Link di questo messaggio
Condividi su altri siti

Non ho capito una ceppa dalla guida (Senz'offesa)

Cioè, non capisco niene di quello che dite...

"SET A, 0" Che significa? cioè non capisco nulla dei comandi e dei numeri :mellow:

Condividi questo messaggio


Link di questo messaggio
Condividi su altri siti

×
×
  • Crea Nuovo...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.