2011-10-24 13 views
7

Aquí hay un código ensamblador del MIPS escribí para probar la instrucción de salto:Instrucción de salto en la Asamblea 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 

Cuando ejecuto el ensamblador, aquí está el resultado:

[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) 

En cuanto a la máquina código para las instrucciones de salto, esto es lo que veo:

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 

de su análisis de estas instrucciones, se ve l Como el código de máquina comienza con un 08 para la instrucción de salto, y el número al final le dice a la instrucción de salto dónde ir. Sin embargo, no puedo entender cómo se calcula este número. Además, no hay nada que me indique que el quinto salto es un salto hacia atrás.

¿Cómo se calcula el valor de salto?

+0

¿por qué usa 3 'agregar $ a0, $ a0, $ a0'? ¿Por qué no usar 'sll $ a0, $ a0, 3' –

Respuesta

12

Basta con consultar el manual de referencia para obtener más información sobre la codificación del código de operación.

Versión corta: en una instrucción de 32 bits no puede incluir un destino de salto de 32 bits. El código de operación usa 6 bits, lo que deja 26 bits para la instrucción. La dirección de destino se construye tomando los primeros 4 bits de la dirección de la instrucción siguiendo la instrucción j, luego se añaden 2 bits cero a los 26 bits del operando de instrucción de salto. (Como las instrucciones son 32 bits, la alineación es útil y permite omitir los dos últimos 0).

Salto hacia atrás: las direcciones son absolutas, NO relativas, por lo que solo depende de la dirección de la instrucción de salto , ya sea un salto hacia adelante o hacia atrás.

EDITAR: Una descripción más detallada: Tenemos en la dirección x instrucción de salto j. Deje t representar el operando de salto de j. t tiene 26 bits de ancho. El patrón de bits de la dirección de la siguiente instrucción se calcula de la siguiente manera:

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

Así que el salto es SIEMPRE absoluta. No hay saltos relativos. cuando el resultado es menor que x, entonces es un salto hacia atrás, cuando es mayor, es un salto hacia adelante (y si quieres algo estúpido, lo haces igual ;-).

Así que veamos en el quinto salto de su ejemplo:

Los primeros 6 bits del destino del salto son: 000000, ya que los 6 bits superiores de la dirección de la instrucción detrás del salto son 000000.

Los siguientes 26 bits son los 26 bits más bajos de la instrucción de salto, es decir 00000000000000000000001000

Los últimos 2 bits son: 00, porque siempre han sido añadidos.

Juntos tenemos: 0000000000000000000000000000100000, que es hex 20. Y en esa dirección se encuentra exactamente la etiqueta/instrucción donde el flujo debe continuar.

+0

Esto no responde a la pregunta sobre cómo la dirección relativa está especificando un desplazamiento hacia atrás. Por lo general, el valor relativo de jmp sería negativo para lograr esto. Además, los desplazamientos anteriores no tienen mucho sentido para los saltos. Yo, al igual que @ z-buffer, también estoy un poco confundido por el desmontaje ... –

+0

Su edición explica el salto como absoluto, pero las compensaciones todavía no se alinean. Debe haber algo más pasando aquí. +1 todavía para responder la pregunta completa. –

+2

@Michael Dorgan: los saltos hacia atrás están bien tal como están: se nota como ... 08. Que 08 izquierda cambió por dos (los dos 2 ceros que mencioné) son 32, que es hex 0x20. Y la instrucción donde van los saltos es 0x..20. Entonces encaja perfectamente (lo mismo con los otros 4 saltos). – flolo

6

En MIPS, J es una instrucción de tipo J:

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

así que tenemos una target que es de 26-bits de longitud. Que se combine con el PC de la siguiente instrucción de la siguiente manera:

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

Se desplaza a la izquierda 2 bits, ya que las instrucciones MIPS (ignorando la extensión MIPS16) son de 32 bits de largo, lo que significa que todos comienzan en una dirección cuya los 2 bits más bajos son cero.

+0

Otra forma de pensarlo es, ¿cuál es el valor más pequeño distinto de cero que puede poner en una instrucción de salto? Eso sería un 1, y corresponde a la 2da instrucción en el programa, que está en 0x4. Así que, básicamente, es un salto a la dirección absoluta de la instrucción, dividida por 4, ya que las direcciones son enésimas. La instrucción es siempre (n-1) * 4. Para dividir por 4, se desplaza a la derecha en 2 bits porque el desplazamiento de n bits derecho divide un número por (2^n). –