Decisiones y bucles
Por defecto, la CPU ejecuta tus instrucciones en el orden en que aparecen, de arriba a abajo. Por sí solo, ese orden nunca puede tomar una decisión ni repetir trabajo. Una bifurcación es la forma en que un programa abandona ese camino recto: evalúa una condición y, cuando la condición se cumple, dirige a la CPU a continuar en un lugar diferente en vez de en la línea siguiente. Toda decisión y todo bucle provienen de este único mecanismo.
No existe if ni for. Los construyes a partir de etiquetas (posiciones con nombre) y bifurcaciones (salto a una posición cuando se cumple una condición). Una etiqueta es un nombre seguido de :.
Para entender cómo se ejecuta una bifurcación, necesitas conocer el Contador de Programa (PC). El PC es un registro especial, oculto a tu código, que contiene la dirección de memoria de la instrucción que se está ejecutando. Una instrucción de bifurcación escribe un nuevo valor en el PC, de modo que la CPU obtiene su siguiente instrucción desde tu etiqueta destino en lugar de desde la línea de código siguiente.
La familia de ramas
Cada bifurcación compara dos registros y salta a la etiqueta solo cuando la prueba se cumple. Cuando la prueba falla, la ejecución continúa en la línea siguiente. Seis pruebas forman el núcleo:
beq a, b, label # salta si a == bbne a, b, label # salta si a != bblt a, b, label # salta si a < b (con signo)bge a, b, label # salta si a >= b (con signo)bltu a, b, label # salta si a < b (sin signo)bgeu a, b, label # salta si a >= b (sin signo)
y comprueban la igualdad e ignoran el signo. y forman el par de ordenación, menor que y mayor o igual que, y comparan los registros como números con signo. y realizan las mismas comparaciones pero tratan los valores como sin signo, lo cual conviene a direcciones o recuentos que nunca son negativos.
¿Qué significan con signo y sin signo? Un registro contiene 32 bits, y los mismos bits pueden leerse de dos maneras. Leídos como sin signo, forman un número entero simple desde 0 hasta unos 4 mil millones. Leídos como con signo, el bit más alto cuenta como signo menos, por lo que la mitad de los patrones de bits representan números negativos. Los bits en sí no cambian. Solo cambia cómo los lees. Por eso hay dos conjuntos de comparaciones: usa las de signo (, ) para números ordinarios que pueden ser negativos, y las sin signo (, ) para valores que nunca son negativos, como las direcciones de memoria.
No existe una "bifurcación si es mayor" ni "bifurcación si es menor o igual" directa. Las obtienes intercambiando los dos registros, y el ensamblador proporciona y como pseudobifurcaciones que realizan el intercambio por ti, de modo que se convierte en . Dos atajos más: y comparan un registro con cero, y salta sin ninguna condición.
li t0, 0 # suma = 0li t1, 1 # i = 1li t2, 6 # límite = 6 (bucle mientras i < 6)loop:bge t1, t2, done # sale del bucle si i >= 6add t0, t0, t1 # suma += iaddi t1, t1, 1 # i++j loop # vuelve a comprobardone:mv a0, t0 # imprime la suma (debería ser 15)li a7, 1ecallli a7, 10ecall
Rastréalo. t0 contiene la suma acumulada (empieza en 0), t1 contiene el contador i (empieza en 1) y t2 contiene el límite 6. En cada pasada por loop: abandona el bucle una vez que i llega a 6. En caso contrario, suma i a la suma, incrementa i en uno, y salta de vuelta para probar de nuevo. El bucle suma 1, 2, 3, 4 y 5, y done imprime el total, 15.
bge compara t1 con t2 para decidir si el bucle continúa.
t1 llega a 6, transfiere el control a done en lugar de dejar que el cuerpo se ejecute de nuevo. Esa prueba es lo que separa una pasada que se repite de la pasada que se detiene.t1 aumenta y el contador de programa (pc) salta de vuelta a loop. Cada vez que pc vuelve a loop, la condición de la bifurcación era falsa, así que el bucle se ejecuta de nuevo.