PDA

View Full Version : [Assembly MC68000] Problema con i vettori - Urgentissimo(Esame a breve)


Eman993
16-09-2015, 18:17
Ciao a tutti ragazzi, mi sto cimentando nella programmazione in assembly(Ho già studiato C++ e qualcosa in java), tuttavia ho un problema nel prendere un vettore e copiarlo in un altro. In pratica supponiamo che i voglia copiare vett1 in vett2:

$ORG 8000
VETT1 DC.B 1,2,3
VETT2 DC.B 0,0,0
N DC.W 3

$ORG 8100
MOVE.W N,D0
LOOP CMP.W #0,D0
BEQ FINE
MOVE.B (VETT1)+,(VETT2)+
ADD.W #-1,D0
JMP LOOP
FINE JMP FINE

Ora la mia domanda è questa: è lecita l'operazione
MOVE.B (VETT1)+,(VETT2)+ ?
Oppure devo semplicemente fare

MOVE.B (VETT1)+,(VETT2)
ADDA #1,VETT2

E' il post-incremento al secondo operando che non mi convince tanto...
Grazie mille per l'aiuto!

cdimauro
16-09-2015, 21:28
Tranquillo: è lecito, e il programma funziona.

cdimauro
17-09-2015, 06:12
Buonanotte (in tutti i sensi): il programma non può funzionare perché non puoi postincrementare VETT1 e VETT2. Infatti DEVONO essere registri indirizzo per poterlo fare. Dunque aggiungi un paio di istruzioni allo scopo, e modifica la MOVE in questione.

Scusami, ma ieri sera ero cotto.

Eman993
17-09-2015, 09:08
Ok dunque dopo aver effettuato la dichiarazione dei vettori devo copiarli in un address register entrambi in questo modo:

LEA VETT1,A0
LEA VETT2,A1

E' lecita tale assegnazione? Oppure utilizzo una MOVEA?

MOVEA.L VETT1,A0

Scusate le tante domande ma il prof. non ci ha dato un libro da cui studiare e ha spiegato queste cose in sole 10 ore di corso :(

cdimauro
17-09-2015, 19:50
Ok dunque dopo aver effettuato la dichiarazione dei vettori devo copiarli in un address register entrambi in questo modo:

LEA VETT1,A0
LEA VETT2,A1

E' lecita tale assegnazione?
Sì, perché la LEA calcola l'indirizzo, e poi lo memorizza nel registro indirizzo.
Oppure utilizzo una MOVEA?

MOVEA.L VETT1,A0

Non esattamente. In questo caso leggeresti una longword (4 byte) a partire dal primo byte di VETT1, e li memorizzeresti in A0.

Dovresti modificare l'istruzione utilizzando la modalità d'indirizzamento immediato, per calcolare l'indirizzo e memorizzarlo così com'è in A0, anziché andare a leggere dove punta:

MOVEA.L #VETT1,A0

Scusate le tante domande ma il prof. non ci ha dato un libro da cui studiare e ha spiegato queste cose in sole 10 ore di corso :(
Purtroppo è un problema abbastanza comune, ma non ti rassegnare: studia per i fatti tuoi e fatti una cultura, che ti servirà dopo gli studi.

Eman993
18-09-2015, 14:27
Ok ora mi è chiaro!
E se volessi passare dal primo al secondo elemento di VETT1 mi basterebbe fare una semplice

ADD.B #1,VETT1

In questo modo avrei che VETT1 punta al secondo suo elemento no?
Grazie sempre per la tua disponibilità!

cdimauro
18-09-2015, 21:15
No, in questo modo incrementeresti di uno il primo elemento di VETT1.

Supponendo che A0 contenga l'indirizzo di VETT1, dovresti fare così:
ADD.L #1,A0
E visto che la costante 1 è "piccola" (da 1 a 10), per ADD e SUB sono disponibili due varianti "veloci", quindi puoi scrivere così:
ADDQ.L #1,A0
Se hai altri dubbi chiedi pure, ma, come vedi, non ti posso rispondere subito: solo quando ho un momento libero (e una tastiera).

Eman993
19-09-2015, 11:09
Come sempre ti ringrazio per la disponibilità! Mi sono imbattuto in un esercizio che chiede di modificare un array utilizzando un sottoprogramma; il vettore deve essere passato tramite stack. Utilizzo l'istruzione PEA per mettere il vettore nello stack e nella subroutine copio l'indirizzo del vettore nel registro address A0(tramite lo stack). Quando vado ad esempio a fare una ADD

ADD.B #1,(A0)

Ho modificato il valore originale del primo elemento del vettore giusto? Le parentesi indicano che sto andando a prendere il dato in memoria all'indirizzo contenuto in A0?

cdimauro
19-09-2015, 14:50
Esattamente.

Eventualmente in futuro riporta il codice (usando il tag CODE), così sarà possibile vedere se è tutto corretto.

Eman993
19-09-2015, 16:21
Perfetto! Credo di iniziare a capirci qualcosa :D anche se avendo già fatto esami di c++ sono avvantaggiato. Comunque adesso sto cercando di scrivere una bozza di driver che gestisca l'input da tastiera di un dato:

ORG $8020
IF_CTRL DC.B 1 Questo è il bit di controllo
ORG $8022
IF_DATA DC.B 1 Questo è il bit data

ORG $8000
START MOVE.B #1,IF_CTRL Asserisco il bit controllo
LOOP BTST.B #7,IF_DATA Aspetto finché la tastiera non termina
BEQ LOOP
MOVE.B IF_DATA,D0 Memorizzo il dato
MOVE.B #0,IF_CTRL deasserisco il control bit
END START

Che ne pensi? Può andare?

cdimauro
19-09-2015, 17:07
Se usi il bit 7 per controllare se c'è un dato da tastiera, sì, va bene.

P.S. Potresti anche usare CLR.B IF_CTRL per azzerare il valore di quella locazione. ;)

Eman993
20-09-2015, 15:11
Grazie mille per tutto! Domani ho l'esame e speriamo vada tutto bene!!!

cdimauro
20-09-2015, 18:21
Ti auguro di fare un buon esame. :)

Eman993
21-09-2015, 14:51
Mauro l'esame non è andato proprio benissimo però me la sono cavata. Ho un dubbio enorme che sarà sicuramente la domanda del prof. all'orale:
Supponiamo di voler scrivere un programma per sostituire in una stringa la lettera a con il simbolo ? e la lettera b con il simbolo !. Ti posto il codice:

ORG $8000
A DC.B 'CASE'
N DC.B 4
B DS.B 1
C1 DC.B 'A'
C2 DC.B 'B'
S1 DC.B '?'
S2 DC.B '!'

ORG $8100
MAIN MOVE.L #B,-(SP)
MOVE.L #A,-(SP)
MOVE.B N,-(SP)
MOVE.B C1,-(SP)
MOVE.B C2,-(SP)
MOVE.B S1,-(SP)
MOVE.B S2,-(SP)
JSR SUB
ADDA #16,SP
END MAIN

In questo modo io voglio mettere il vettore modificato dentro la variabile B. Ma ho fatto bene a dichiararla in questo modo? Cioè è un vettore vuoto quello lì? Quando la subroutine farà

MOVE.B 5(SP),D0
MOVE.L 16(SP),A0
MOVE.B D0,(A0)+
B "Diventerà" un array?
Perché in C++ quando voglio dichiarare una variabile faccio int i. Quando voglio dichiarare un array faccio int i[n]. In assembler c'è questa differenza?
P.S. il prof. ci tiene alla riusabilità del codice, quindi se ho fatto qualcosa di troppo particolare e poco generico me lo indichi? Grazie mille!

cdimauro
21-09-2015, 21:09
Mauro
Cesare. :)
l'esame non è andato proprio benissimo però me la sono cavata.
Benissimo. Lo scritto è un grosso scoglio, e averlo superato è già una gran cosa. Complimenti.
Ho un dubbio enorme che sarà sicuramente la domanda del prof. all'orale:
Supponiamo di voler scrivere un programma per sostituire in una stringa la lettera a con il simbolo ? e la lettera b con il simbolo !. Ti posto il codice:

ORG $8000
A DC.B 'CASE'
N DC.B 4
B DS.B 1
C1 DC.B 'A'
C2 DC.B 'B'
S1 DC.B '?'
S2 DC.B '!'

ORG $8100
MAIN MOVE.L #B,-(SP)
MOVE.L #A,-(SP)
MOVE.B N,-(SP)
MOVE.B C1,-(SP)
MOVE.B C2,-(SP)
MOVE.B S1,-(SP)
MOVE.B S2,-(SP)
JSR SUB
ADDA #16,SP
END MAIN

In questo modo io voglio mettere il vettore modificato dentro la variabile B. Ma ho fatto bene a dichiararla in questo modo? Cioè è un vettore vuoto quello lì?
Non è un vettore vuoto: hai dichiarato la variabile B che è costituita di 1 solo byte. Poiché il vettore A è di 4 byte, non avrai abbastanza spazio e finirai per sovrascrivere C1, C2, ed S1.

Adesso non ricordo se la sintassi dell'assembler lo preveda, ma può darsi che tu possa dichiarare N e B in questo modo:
N DC.B N-A
B DS.B N-A
N-A è la distanza fra N e A in termini di byte. Poiché N si trova esattamente dopo A, N-A sarà 4.

In realtà non avresti bisogno di dichiarare N, C1, C2, S1, ed S2 come variabili, ma semplicemente come costanti. Lo si fa usando EQU al posto di DC:
A DC.B 'CASE'
B DS.B B-A
N EQU B-A
C1 EQU 'A'
C2 EQU 'B'
S1 EQU '?'
S2 EQU '!'

Ma in tal caso al posto di
MOVE.B N,-(SP)
ad esempio, dovrai usare l'indirizzamento immediato:
MOVE.B #N,-(SP)

Altra cosa importante, anche se utilizzi la MOVE.B, quando inserisci un dato nello stack, il "taglio" minimo è rappresentato da una word, per cui scriverai 2 byte anziché 1. Tienine conto quando devi farti i conti per vedere dove si trovano i tuoi parametri nello stack.
Quando la subroutine farà

MOVE.B 5(SP),D0
MOVE.L 16(SP),A0
MOVE.B D0,(A0)+

Intanto ti consiglio di definire delle costanti per gli offset di ogni parametro che si trova nello stack, altrimenti diventi matto a tenere i conti ogni volta che ti serve una variabile.
B "Diventerà" un array?
Perché in C++ quando voglio dichiarare una variabile faccio int i. Quando voglio dichiarare un array faccio int i[n]. In assembler c'è questa differenza?
In assembly faresti:
i DS.B n
P.S. il prof. ci tiene alla riusabilità del codice, quindi se ho fatto qualcosa di troppo particolare e poco generico me lo indichi? Grazie mille!
Visto che usi una subroutine e gli passi tutti i parametri, direi che è abbastanza generico.

In ogni caso devi tenere presente che il tuo obiettivo è risolvere l'esercizio. Quindi non ti complicare la vita: implementa la soluzione più semplice che ti viene in mente e che lo risolve pienamente. Poi se c'è qualcosa da migliorare, ci penserai dopo, SE avrai tempo e avrà senso la modifica.

Eman993
23-09-2015, 16:10
Perfetto! Direi che a meno di grosse sviste domani dovrebbe andare tutto bene, grazie mille ancora e scusa se ti ho chiamato Mauro (cdiMAURO) :D

cdimauro
23-09-2015, 20:53
Non ti preoccupare: mi capita spesso, e non potevi sapere. ;)

Allora fai un buon orale e prenditi questa materia. :)