Control de Flujo en MIPS
Ciencias de la Computación III
Diego José Figueroa
Primero, algunos convenios...
- i, j son enteros.
- c es un caracter.
- s es un puntero a un char (un string).
- Las variables están mapeadas a los registros $s0 - $s7 (en orden de aparición).
¿Qué formas de control de flujo necesitamos?
Control de Flujo
- Go-to
- if-then-else
- for
- while
- do-while
- Llamadas a funciones.
- Llamadas indirectas a funciones.
- Excepciones.
Control de Flujo
- Go-to
- En MIPS -> saltos incondicionales
- Ciclos y condicionales (if-then-else, for, while...)
- En MIPS -> saltos condicionales
- Llamadas a funciones y algunas excepciones
- En MIPS -> jump-and-link, jump-register
- Punteros a funciones, algunas excepciones
- En MIPS -> jump-and-link-register
Saltos incondicionales
j label
- Salta a la dirección indicada por la etiqueta.
- La dirección puede ser muy grande (hasta 26 bits).
- Traducción directa de un go-to.
go-to -> jump
goto label;
...
label: code
Se traduce a
j label
...
label: code
Saltos condicionales (branches)
- Permiten saltar a una dirección sólo si se cumple una condición.
beq rs rt label
- Tenemos
-
beq - Branch if equal
- bne - Branch if not equal
- bgtz - Branch if greater than zero
- bgez - Branch if greater or equal than zero
- bltz - Branch if less than zero
- blez - Branch if less or equal than zero
- Limitados a saltos no mayores a 2^15 instrucciones.
if-then
if(i != j){
code; }
beq $s0 $s1 done
code
done:
Notar la lógica invertida en la condición!
if-then-else
if(i == j){
code_1
} else {
code_2
}
Se traduce a
bne $s0 $s1 else code_1 j done else:
code_2 done:
switch
switch(c){
case 'a': code_1;
break;
case 'b': code_2;
case 'c': code_3;
break;
default : code_4; }
switch
li $t0 'a' beq $t0 $s0 a_case
li $t0 'b' beq $t0 $s0 b_case
li $t0 'c' beq $t0 $s0 c_case j default
a_case: code_1
j done b_case:
code 2 c_case: code 3 j done default:
code_4
done:
do-while
do { code; i++;
} while(i < j)
Se traduce a
do_start:
code addi $s0 $s0 1 blt $s0 $s1 do_start
while
int i = 42;
while(i != 0){
i--;
}
se traduce a
li $s0 42
test:
beq $s0 $0 done
subi $s0 $s0 1
j test
done:
for
for(i = 0; i < j; i++){
code;
}
Se traduce a
li $s0 0
test:
beq $s0 $s1 done
code
addi $s0 $s0 1
j test
done:
Operaciones de comparación
- Muchas de las operaciones de comparación son en realidad psuedo-instrucciones.
- El ensamblador se encarga de traducirlas a instrucciones reales.
- Basado en la instrucción slt.
- slt - Set less than
- sltu, slti, sltui.
- Si la condición
- es verdadera, asigna 1 a un registro.
- es falsa, asigna 0 a un registro.
slt
# $t0 = ($s0 < $s1) ? 1 : 0
slt $t0 $s0 $s1
&& y ||
- Comúnmente se implementan con S.C.E
- Short-circuit-evaluation
i = (s != NULL) && (*s)
se traduce a
sne $t0 $s1 $zero # $t0 = s!=NULL beqz $t0 skip # ya es falso lw $t0 0($s1) sne $t0 $t0 $zero # $t0 = (*s) != '\0' skip:
add $s0 $t0 $zero # $s0 = $t0
Llamadas a funciones
- ¿Qué implica una llamada a una función?
- Saltar a una instrucción
- Registrar a dónde debemos regresar.
- Regresar a la instrucción correcta.
Diferentes implementaciones
- Algunas arquitecturas implementan un stack de llamadas
-
Y agregan intrucciones especiales.
-
Que permiten entrar o salir.
- Puede ser algo complejo.
- MIPS opta por utilizar saltos
- jr
- jal
- jalr
jal (jump-and-link)
jal label
- Transfiere el control (salta) a la instrucción indicada por la etiqueta
- Al igual que la instrucción j.
- Adicionalmente, coloca la dirección de la instrucción siguiente en el registro $ra.
- Esto nos permite saber a dónde debemos regresar!
jr (jump-register)
jr rs
- Transfiere el control (salta) a la instrucción indicada por la dirección en el registro rs.
- Apto para saltos muy grandes.
- Al usarlo en conjunto con jal, se logran hacer llamadas a funciones.
jal y jr
.data bar_str: .asciiz ”- bar\n” foo_str: .asciiz ”foo -" .text main:
jal foo puts bar_str j done
... foo:
puts foo_str jr $ra
done:
...
06 - Flow Control
By Diego Figueroa
06 - Flow Control
- 961