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;
}
Se traduce a
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_4done:

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 42test:      beq $s0 $0 done      subi $s0 $s0 1      j testdone:

for

for(i = 0; i < j; i++){
      code;
}
Se traduce a
li $s0 0test:      beq $s0 $s1 done      code      addi $s0 $s0 1      j testdone:

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