2011-10-03 14 views
5

Sto studiando il linguaggio dell'assemblaggio MIPS e ho trovato questo esempio nel libro e per me sembra scorretto. Se è così non sarebbe il primo errore che ho trovato in questo libro.Converti C in MIPS - Matrici annidate

Le variabili f e g registri sono assegnati $s0 e $s1 rispettivamente, gli indirizzi di base per le matrici A e B sono $s6 e $s7 rispettivamente.

L'esempio di codice c è:

f = g - A[B[4]]; 

E il corrispondente complesso di MIPS fornite sono:

lw $t0, 16($s7) 
lw $s0, 0($t0) 
sub $s0, $s1, $s0 

Dalla mia comprensione del codice sopra MIPS sarebbe caricare alcuni dati casuali dalla memoria all'indirizzo fornito per $t0 e quindi sottrarre da $s1 e non accedere all'indice $t0 dell'array denotato in $s6.

L'assemblea MIPS corretta dalla mia comprensione sarebbe lungo le linee di:

lw $t0, 4($s7) 
add $t0, $t0, $s6 
sll $t0, $t0, 2 
lw $s0, 0($t0) 
sub $s0, $s1, $s0 

ho ragione che si tratta di un errore nel libro o sto malinteso qualcosa.


Edit: Corretto un errore nel codice MIPS corretto come sottolineato da Chris Dodd

+3

Penso che tu abbia ragione. Molto bene! – davin

+1

La tua spiegazione è eccellente. La più grande prova del fatto che quel codice non sta facendo quello che dovrebbe, è che non si fa menzione di '$ s6', quindi non c'è modo di recuperare un elemento dall'array' A'. – davin

+4

Supponendo che l'array A sia 4 byte per elemento (come sembra essere l'array B - stai usando un offset di 16 per ottenere l'elemento 4, e usando le istruzioni di lw per ottenere 4 byte), dovrai aggiungere un moltiplicare per 4 anche qui (o uno spostamento equivalente di 2) –

risposta

0

Come ho sottolineato molti, c'è stato un errore nel libro. Da quando ho scoperto questo errore ho trovato diversi errori di questo tipo.

-1

Ma potrebbe benissimo essere che l'autore copiato il codice prima fase di collegamento. Ciò lascerebbe aperta la possibilità che il linker riempie l'indirizzo di memoria di A [] al posto del 0 nell'istruzione

lw $s0, 0($t0) 

nell'eseguibile finale. Non so se MIPS consente gli offset di tale dimensione (ovvero, l'intervallo di indirizzi in cui A [] viene posizionato infine). Questo naturalmente non è un buon modo per spiegare qualcosa in un libro, rompendo le proprie premesse in silenzio e generalmente non sapendo cosa sta succedendo.

+1

Questo non funzionerebbe in quanto l'offset è un offset di byte a 16 bit con segno e '$ s6' potrebbe in teoria utilizzare l'intero intervallo di indirizzi a 32 bit. È molto più probabile che sia semplicemente un errore nel libro. (Inoltre, non penso che nessun linker MIPS farebbe questo tipo di ottimizzazione in quanto sarebbe davvero sgradevole con l'offset relativo e dovendo affrontare casi in cui l'offset è troppo grande) – user786653

+0

Nessun assemblatore/linker sane lo farebbe mai. Non c'è assolutamente alcuna confusione su ciò che fa quell'istruzione. Questo è un carico esplicito con un indirizzo reg + imm. Non è come un compilatore per un HLL che può inserire qualsiasi istruzione desideri. –

4

Questo è per tutti (probabilmente studenti CprE 381) che potrebbero imbattersi in questo cercando un buon esempio. Il codice modificato dell'OP è ancora errato. L'offset nella prima parola di caricamento dovrebbe essere 16. Potrebbe essere 4 se la larghezza di memoria è di 32 bit, ma in tal caso non sarebbe necessario lo spostamento/moltiplicazione. Supponendo che la memoria sia larga 8 bit, è necessario cambiare le funzioni di aggiunta e di spostamento. Nel codice OP, moltiplica l'indirizzo di A [B [4]/4] di 4. Spostando/moltiplicando per primo si ottiene l'indice corretto. Il codice corretto è:

lw $t0, 16($s7) # gets the value of B[4] 
        # offset could be 4 depending on memory width 
        # but then the shift would not be needed 
sll $t0, $t0, 2 # this multiplies the index by 4 to get the address offset 
add $t0, $t0, $s6 # adds the base address of A and the offset 
lw $t0, 0($t0) # loads the value at the address 
sub $s0, $s1, $t0 # performs subtraction and stores in f 

Nel caso qualcuno è confuso su tutta offset del 16 vs 4 e se è necessario il turno, mi spiego. Se la larghezza della memoria è di 32 bit, è possibile memorizzare un intero intero a 32 bit in un'unica posizione di memoria. Se questo è il caso, l'indice dell'array è uguale all'offset dell'indirizzo. Tuttavia, se la memoria è larga solo 8 bit (1 byte), allora un numero intero a 32 bit viene memorizzato su 4 posizioni di memoria (1 indirizzo per ogni byte). Questo è il motivo per cui è necessario spostare l'indice di 2 (o moltiplicarlo per 4) per ottenere l'offset corretto dell'indirizzo.