El procesador puede utilizar algunas instrucciones para tomar decisiones,
similares a una instrucción if con goto:
beq $1,$2,L1
significa ir a (goto) la sentencia rotulada L1 si el valor de $1
es igual al valor de $2. También:
bne $1,$2,L1
significa ir a (goto) la sentencia rotulada L1 si el valor de $1 es
distinto al valor de $2.
Ejemplo 4.
En el siguiente segmento de código C, s, x, y, i y j son variables, entonces:
if ( i == j) goto L1; s = x + y; L1: s = s -i;
El programa compilado es el siguiente:
beq $19,$20,L1 # ir a L1 si i igual a j.
add $16,$17,$18 # s=x+y, saltada si i igual a j.
L1: sub $16,$16,$19 # s=s-i, siempre ejecutada.
En los computadores de programa almacenado las instrucciones se almacenan en memoria;
por consiguiente, las instrucciones deben tener direcciones de memoria igual que los demás datos
de un programa. El rótulo L1 corresponde a la dirección de la instrucción restar.
Los compiladores crean frecuentemente saltos y rótulos cuando no aparecen en el
lenguaje de programación. Utilizando las mismas variables y registros del ejemplo anterior, el
código C:
if ( i == j) s = x+y; else s = x-y;
se transforma en:
bne $19,$20,Else # ir a Else si i distinto a j.
add $16,$17,$18 # s=x+y, saltada si i distinto a j.
j Exit # ir a Exit
Else: sub $16,$17,$18 # s=x-y, saltada si igual a j.
Ejemplo 5.
Dado el siguiente loop en C:
Loop: s = s + A[i];
i = i + j;
if (i != x) goto Loop;
supongamos que el compilador asocia las variables s, x, i y j a los registros $17,$18,$19 y $20, respectivamente. Supongamos también que el arreglo comienza en la dirección Tabla. Se debe notar que el direccionamiento es en bytes y significa que se debe multiplicar el índice i por 4 antes de poder utilizarlo en la instrucción de carga.
Loop: mult $9,$19,$10 # $9 =i*4, cálculo dirección.
lw $8,Tabla($9) # $8 =A[i].
add $17,$17,$8 # s=s+A[i].
add $19,$19,$20 # i=i+j.
bne $19,$18,Loop # ir a Loop si distinto a x.
Para evitar el uso de gotos a nivel de lenguaje C, podemos escribir
lo siguiente:
Ejemplo 6.
while ( reg[i] == x )
i=i+j;
si asociamos las variables i, j y x con $19, y $20 y $21, crespectivamente, el array reg comienza en la dirección Sreg y el registro $10 contiene el valor 4, entonces:
Loop: mult $9,$19,$10 # $9 =i*4, cálculo dirección.
lw $8,Sreg($9) # $8 =reg[i].
bne $8,$21,Exit # ir a Exit si reg[i] distinto a x.
add $19,$19,$20 # i=i+j.
j Loop # ir a Loop.
Exit: ...
Para ver si una variable es menor que otra, utilizamos la instrucción slt (set on
less than). Por ejemplo:
Ejemplo 7.
slt $8,$19,$20
significa que el registro $8 se pone en 1 si el valor del registro $19 es menor que el valor del registro $20; en caso contrario $8 toma el valor
0.
¿Qué significa el siguiente código?
slt $1,$16,$17 # $1 es 1 si $16 < $17.
bne $1,$0,Menor # ir a Menor si $1 <> $0 (cero).
¿Qué pasa con las instrucciones de selección múltiple, tales como case o switch?. La versión C de la instrucción case(Pascal) se denomina switch. El siguiente código C selecciona entre cuatro alternativas según el valor de k (0, 1, 2 ó 3). Suponer que las seis variables corresponden a los registros $16 a $21, y que el registro $10 contiene el valor 4.
switch (k) {
case 0: f=i+j; break; /*k=0*/
case 1: f=g+h; break; /*k=1*/
case 2: f=g-h; break; /*k=2*/
case 3: f=i-j; break; /*k=3*/
}
El siguiente código en lenguaje assembly es el equivalente. Suponiendo que el arreglo JumpTable contiene las direcciones correspondientes a los labels L0, L1, L2, y L3, respectivamente. La variable k debe ser multiplicada por 4 para convertirla a su dirección equivalente en bytes:
mult $9,$19,$21 # $9=k*4.
lw $8,JumpTable($9) # $8=JumpTable[k].
jr $8 # salta según contenido de $8.
L0: add $16,$19,$20 # k=0, f = i+j.
j Exit # ir a Exit.
L1: add $16,$17,$18 # k=1, f = g+h.
j Exit # ir a Exit.
L2: add $16,$17,$18 # k=2, f = g-h.
j Exit # ir a Exit.
L3: add $16,$19,$20 # k=3, f = i-j.
Exit: