2011-10-24 5 views
7

Ecco alcuni codice assembly MIPS che ho scritto per testare l'istruzione di salto:Istruzione di salto in Assembly MIPS

addi $a0, $0, 1 
j next 
next: 
j skip1 
add $a0, $a0, $a0 
skip1: 
j skip2: 
add $a0, $a0, $a0 
add $a0, $a0, $a0 
skip2: 
j skip3 
loop: 
add $a0, $a0, $a0 
add $a0, $a0, $a0 
add $a0, $a0, $a0 
skip3: 
j loop 

Quando eseguo l'assemblatore, ecco il risultato:

[0x000000] 0x20040001 # addi $a0, $zero, 1 ($a0 = 1) 
[0x000004] 0x08000002 # j 0x0002 (jump to addr 0x0008) 
[0x000008] 0x08000004 # j 0x0004 (jump to addr 0x0010) 
[0x00000C] 0x00842020 # add $a0, $a0, $a0 ($a0 = $a0 + $a0) 
[0x000010] 0x08000007 # j 0x0007 (jump to addr 0x001C) 
[0x000014] 0x00842020 # add $a0, $a0, $a0 ($a0 = $a0 + $a0) 
[0x000018] 0x00842020 # add $a0, $a0, $a0 ($a0 = $a0 + $a0) 
[0x00001C] 0x0800000B # j 0x000B (jump to addr 0x002C) 
[0x000020] 0x00842020 # add $a0, $a0, $a0 ($a0 = $a0 + $a0) 
[0x000024] 0x00842020 # add $a0, $a0, $a0 ($a0 = $a0 + $a0) 
[0x000028] 0x00842020 # add $a0, $a0, $a0 ($a0 = $a0 + $a0) 
[0x00002C] 0x08000008 # j 0x0008 (jump to addr 0x0020) 

Guardando alla macchina codice per le istruzioni di salto, questo è quello che vedo:

1st jump (just jumps to next instruction) 0x08000002 
2nd jump (skips 1 instruction) 0x08000004 
3rd jump (skips 2 instructions) 0x08000007 
4th jump (skips 3 instructions) 0x0800000B 
5th jump (skips 3 instructions backwards) 0x08000008 

Dall'esame di queste istruzioni, sembra l ike il codice macchina inizia con un 08 per l'istruzione di salto, e il numero alla fine dice all'istruzione di salto dove andare. Tuttavia, non riesco a capire come viene calcolato questo numero. Inoltre, non c'è nulla che indichi che il 5 ° salto è un salto all'indietro.

Come viene calcolato il valore di salto?

+0

perché usi 3 'aggiungi $ a0, $ a0, $ a0'? perché non usare 'sll $ a0, $ a0, 3' –

risposta

12

Basta esaminare un manuale di riferimento per ulteriori dettagli sulla codifica opcode.

Versione corta: in un'istruzione a 32 bit non è possibile includere una destinazione di salto a 32 bit. L'opcode utilizza 6 bit, che lascia 26 bit per l'istruzione. L'indirizzo di destinazione è costruito prendendo i primi 4 bit dell'indirizzo dell'istruzione seguendo l'istruzione j, quindi 2 bit zero vengono aggiunti ai 26 bit dell'operando dell'istruzione di salto. (Poiché le istruzioni sono 32 bit, l'allineamento è utile e consente l'omissione degli ultimi due 0)

Al salto all'indietro: gli indirizzi sono assoluti, NON relativi, quindi dipende solo dall'indirizzo dell'istruzione di salto , che si tratti di un salto in avanti o all'indietro.

EDIT: Una descrizione più dettagliata: Abbiamo all'indirizzo x istruzione di salto j. Let t t rappresenta l'operando jump di j. t è largo 26 bit. Il modello di bit di indirizzo della successiva istruzione viene calcolato come segue:

upper_6_bits_of(x+4),t,0,0 

Quindi il salto è SEMPRE assoluta. Non ci sono salti relativi. quando il risultato è minore di x, allora è un salto all'indietro, quando è maggiore è un salto in avanti (e se vuoi qualcosa di stupido, lo rendi uguale ;-).

Quindi diamo un'occhiata al 5 ° salto del vostro esempio:

I primi 6 bit della destinazione di salto sono: 000000, perché i superiori 6 bit dell'indirizzo dell'istruzione dietro il salto sono 000000.

i successivi 26 bit sono i più bassi di 26 bit della istruzione di salto, che è 00000000000000000000001000

gli ultimi 2 bit sono: 00, perché la Got sempre aggiunto.

Insieme abbiamo: 0000000000000000000000000000100000, che è hex 20. E a quell'indirizzo è esattamente l'etichetta/istruzione dove il flusso dovrebbe continuare.

+0

Questo non risponde alla domanda su come l'indirizzo relativo sta specificando un offset all'indietro. Di solito, il valore relativo jmp sarebbe negativo per ottenere ciò. Inoltre, gli offset di cui sopra non hanno molto senso per i salti. Io, come @ z-buffer, sono anche un po 'confuso dallo smontaggio ... –

+0

La tua modifica spiega il salto come assoluto, ma gli offset non si allineano ancora. Deve esserci qualcos'altro che sta succedendo qui. +1 ancora per rispondere alla domanda completa. –

+2

@ Michael Dorgan: I salti all'indietro vanno bene così: mostra come ... 08. Quella 08 sinistra spostata di due (i due 2 zeri che ho menzionato) sono 32, che è l'esadecimale 0x20. E l'istruzione dove vanno i salti è 0x..20. Quindi si adatta perfettamente (lo stesso vale per gli altri 4 salti). – flolo

6

In MIPS, J è un'istruzione J-type:

J-type instructions (Jumps) 
3 22 
1 65      0 
+----+-------------------------+ 
| op |   target   | 
+----+-------------------------+ 

così abbiamo una target che è lungo 26 bit. Esso viene combinato con il PC della successiva istruzione come segue:

I 
I+1 PC <- (PC & 0xf0000000) | (target << 2) 

E 'spostato a sinistra 2 bit, dal momento che le istruzioni MIPS (ignorando l'estensione mips16) sono lunghe 32 bit, il che significa che tutti cominciano in un discorso il cui i 2 bit inferiori sono zero.

+0

Un altro modo per pensarci è, qual è il più piccolo valore diverso da zero che puoi inserire in un'istruzione di salto? Quello sarebbe un 1 e corrisponde alla seconda istruzione nel programma, che è a 0x4. Quindi in pratica si tratta di un salto verso l'indirizzo assoluto dell'istruzione, diviso per 4, dato che l'ennesima istruzione è sempre (n-1) * 4. Per dividere per 4, si sposta a destra di 2 bit perché lo spostamento di n bit a destra divide un numero di (2^n). –