View Full Version : [Assembly MC68000] Problema con i vettori - Urgentissimo(Esame a breve)
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.
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.
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).
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.
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. ;)
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. :)
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.
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. :)
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.