Estructura de Computadores Tema 3. Programación en ensamblador Departamento de Informática Grupo de Arquitectura de Computadores, Comunicaciones y Sistemas UNIVERSIDAD CARLOS III DE MADRID Contenido n Fundamentos básicos de la programación en ensamblador n Ensamblador del MIPS 32, modelo de memoria y representación de datos n Formato de las instrucciones y modos de direccionamiento n Llamadas a procedimientos y uso de la pila ARCOS Estructura de Computadores 2 Procedimientos n Un procedimiento (función, subrutina) es un subprograma que realiza una tarea especifica cuando se le invoca q Recibe argumentos o parámetros de entrada q Devuelve algún resultado n En ensamblador un procedimiento se asocia con un nombre simbólico que denota su dirección de inicio (la dirección de memoria donde se encuentra la primera instrucción) ARCOS Estructura de Computadores 3 Pasos en la ejecución de un procedimiento/función n Situar los parámetros en un lugar donde el procedimiento n n n n n pueda accederlos. Transferir el control al procedimiento. Adquirir los recursos de almacenamiento necesarios para el procedimiento. Realizar la tarea deseada. Poner el resultado en un lugar donde el programa o procedimiento que realiza la llamada pueda accederlo. Devolver el control al punto de origen. ARCOS Estructura de Computadores 4 Funciones en un lenguaje de alto nivel 5 int main() { int z; z=factorial(x); print_int(z); } ARCOS int factorial(int x) { int i; int r=1; for (i=1;i<=x;i++) { r*=i; } return r; } Estructura de Computadores 5 Funciones en un lenguaje de alto nivel 6 int main() { int z; z=factorial(x); print_int(z); } ARCOS int factorial(int x) { int i; int r=1; for (i=1;i<=x;i++) { r*=i; } return r; } Estructura de Computadores 6 Funciones en un lenguaje de alto nivel 7 int main() { int z; z=factorial(x); print_int(z); } ARCOS int factorial(int x) { int i; int r=1; for (i=1;i<=x;i++) { r*=i; } return r; } Estructura de Computadores 7 Funciones en un lenguaje de alto nivel 8 int main() { int z; z=factorial(x); print_int(z); } ARCOS int factorial(int x) { int i; int r=1; for (i=1;i<=x;i++) { r*=i; } return r; } Estructura de Computadores 8 Funciones en un lenguaje de alto nivel 9 int main() { int z; z=factorial(x); print_int(z); } ARCOS int factorial(int x) { int i; int r=1; for (i=1;i<=x;i++) { r*=i; } return r; } Estructura de Computadores 9 Funciones en un lenguaje de alto nivel 10 int main() { int z; z=factorial(x); print_int(z); 4 } 3 ARCOS 1 2 int factorial(int x) { int i; int r=1; for (i=1;i<=x;i++) { r*=i; } return r; } Estructura de Computadores 10 Funciones en un lenguaje de alto nivel 11 int main() { int z; z=factorial(x); print_int(z); } Variables locales ARCOS int factorial(int x) { int i; int r=1; for (i=1;i<=x;i++) { r*=i; } return r; } Estructura de Computadores 11 Llamadas a funciones en MIPS 12 Llamada a función en el MIPS (instrucción jal) factorial: … jal factorial … jr $ra factorial representa la dirección de inicio de la subrutina (función) ARCOS Estructura de Computadores 12 Llamadas a funciones en MIPS 13 0x00401000 factorial: 0x00001000 0x00001004 … jal 0x00401000 … jr $ra $ra = PC = 0x00001004 PC = 0x00401000 ARCOS Estructura de Computadores 13 Llamadas a funciones en MIPS 14 0x00401000 0x00001000 0x00001004 … jal 0x00401000 … jr $ra $ra = 0x00001004 ARCOS Estructura de Computadores 14 Llamadas a funciones en MIPS 15 Retorno de subrutina (instrucción jr ) 0x00401000 0x00001000 0x00001004 … jal 0x00401000 … jr $ra PC = $ra = 0x00001004 $ra = 0x00001004 ARCOS Estructura de Computadores 15 Llamadas a funciones en MIPS 16 0x00401000 0x00001000 0x00001004 … jal 0x00401000 … jr $ra PC = $ra = 0x00001004 ARCOS Estructura de Computadores 16 Instrucciones jal/jr 17 n ¿Qué hace la instrucción jal? q $ra ß $PC q $PC ß Dirección de salto n ¿Qué hace la instrucción jr? q $PC ß $ra ARCOS Estructura de Computadores 17 Llamadas anidadas 0x00401000 jal 0x000080000 … 0x00001000 jal 0x00401000 0x00001004 … 0x00008000 jr $ra jr $ra ARCOS Estructura de Computadores 18 Llamadas anidadas 0x00401000 jal 0x000080000 … 0x00001000 jal 0x00401000 0x00001004 … 0x00008000 jr $ra jr $ra $ra = PC = 0x00001004 PC = 0x00401000 ARCOS Estructura de Computadores 19 Llamadas anidadas 0x00401000 0x00401020 jal 0x000080000 0x00401024 … 0x00001000 jal 0x00401000 0x00001004 … 0x00008000 jr $ra jr $ra $ra = PC = 0x00401024 PC = 0x00008000 ARCOS Estructura de Computadores 20 Llamadas anidadas 0x00401000 0x00401020 jal 0x000080000 0x00401024 … 0x00001000 jal 0x00401000 0x00001004 … 0x00008000 jr $ra jr $ra PC = $ra = 0x00401024 ARCOS Estructura de Computadores 21 Llamadas anidadas 0x00401000 0x00401020 jal 0x000080000 0x00401024 … 0x00001000 jal 0x00401000 0x00001004 … 0x00008000 jr $ra jr $ra ? PC = $ra = 0x00401024 ARCOS Estructura de Computadores 22 Llamadas anidadas 0x00401000 0x00401020 jal 0x000080000 0x00401024 … 0x00001000 jal 0x00401000 0x00001004 … 0x00008000 jr $ra ? jr $ra PC = $ra = 0x00401024 Se ha perdido la dirección de retorno ARCOS Estructura de Computadores 23 ¿Dónde guardar la dirección de retorno? n El computador dispone de dos elementos para almacenamiento: q Registros q Memoria n No se pueden utilizar los registros porque su número es limitado n Se guarda en memoria principal q En una zona del programa que se denomina pila ARCOS Estructura de Computadores 24 Ejecución de un programa Memoria Principal Sistema Operativo Disco instrucciones Programa en ejecucion datos Fichero ejecutable pila ARCOS Estructura de Computadores 25 Mapa de memoria de un proceso memoria Segmento de Texto pc 01011001 Segmento de Datos $sp 01011001 n El programa de usuario se divide en segmentos: q Segmento de código (texto) n Código, instrucciones máquina q Segmento de datos n Datos estáticos, variables globales q Segmento de pila n Variables locales n Contexto de funciones Segmento de Pila ARCOS Estructura de Computadores 26 Pila PUSH Reg Apila el contenido del registro (dato) dato cima $sp $sp cima crece hacia direcciones bajas ARCOS Estructura de Computadores 27 Pila POP Reg dato Desapila el contenido del registro (dato) Copia dato en el registro Reg $sp dato cima cima $sp crece hacia direcciones bajas ARCOS Estructura de Computadores 28 Antes de empezar 29 n MIPS no dispone de instrucciones PUSH o POP. n El registro puntero de pila ($sp) es visible al programador. q Se va a asumir que el puntero de pila apunta al último elemento de la pila PUSH $t0 POP $t0 lw $t0, ($sp) addu $sp, $sp, 4 addu $sp, $sp, -4 sw $t0, ($sp) ARCOS Estructura de Computadores 29 Operación PUSH en el MIPS 7 $sp 8 Estado inicial: el registro puntero de pila ($sp) apunta al último elemento situado en la cima de la pila ARCOS Estructura de Computadores 30 Operación PUSH en el MIPS $sp 7 8 addu $sp, $sp, -4 Se resta 4 al registro puntero de pila para poder insertar una nueva palabra en la pila ARCOS Estructura de Computadores 31 Operación PUSH en el MIPS 9 $sp 7 8 li sw $t2, 9 $t2 ($sp) Se inserta el contenido del registro $t2 en la cima de la pila ARCOS Estructura de Computadores 32 Operación POP en el MIPS 9 $sp 7 8 lw $t2 ($sp) Se copia en $t2 el dato almacenado en la cima de la pila (9) ARCOS Estructura de Computadores 33 Operación POP en el MIPS 9 7 $sp 8 addu $sp, $sp, 4 Se actualiza el registro puntero de pila para apuntar a la nueva cima de la pila. El dato desapilado (9) sigue estando en memoria pero será sobrescrito en futuras operaciones PUSH ARCOS Estructura de Computadores 34 Pila uso de push y pop consecutivos push $a0 push $t1 push $t2 push $s2 ... pop $s2 pop $t2 pop $t1 pop $a0 ARCOS Estructura de Computadores 35 Pila uso de push y pop consecutivos addu $sp $sp -4 push push push push $a0 $t1 $t2 $s2 sw $a0 ($sp) addu $sp $sp -4 sw $t1 ($sp) addu $sp $sp -4 sw $t2 ($sp) addu $sp $sp -4 ... sw $s2 ($sp) ... pop pop pop pop $s2 $t2 $t1 $a0 lw $s2 ($sp) addu $sp $sp 4 lw $s2 ($sp) addu $sp $sp 4 lw $s2 ($sp) addu $sp $sp 4 lw $s2 ($sp) addu $sp $sp 4 ARCOS Estructura de Computadores 36 Pila uso de push y pop consecutivos push push push push $a0 $t1 $t2 $s2 ... pop pop pop pop addu $sp $sp -16 sw $a0 12($sp) sw $t1 8($sp) sw $t2 4($sp) sw $s2 ($sp) ... $s2 $t2 $t1 $a0 lw $s2 ($sp) lw $t2 4($sp) lw $t1 8($sp) lw $a0 12($sp) addu $sp ARCOS Estructura de Computadores $sp 16 37 Ejemplo (1) Se parte de un código en lenguaje de alto nivel 38 int main() { int z; z=factorial(5); print_int(z); . . . } ARCOS int factorial(int x) { int i; int r=1; for (i=1;i<=x;i++) { r*=i; } return r; } Estructura de Computadores 38 Ejemplo (2) Pensar en el paso de parámetros 39 n Los parámetros en el MIPS se pasan en $a0, $a1, $a2 y $a3 n Los resultados en el MIPS se recogen en $v0, $v1 n Más adelante se verá con más detalle n Si se necesita pasar más de cuatro parámetros, los cuatro primeros en los registros $a0, $a1, $a2 y $a3 y el resto en la pila n En la llamada z=factorial(5); n Un parámetro de entrada: en $a0 n Un resultado en $v0 ARCOS Estructura de Computadores 39 El parámetro se pasa en $a0 El resultado se devuelve en $v0 Ejemplo (3) Se pasa a ensamblador cada función 40 int main() { int z; z=factorial(5); print_int(z); . . . } int factorial(int x) { int i; int r=1; for (i=1;i<=x;i++) { r*=i; } return r; } ARCOS li $a0, 5 jal factorial move $a0, $v0 li $v0, 1 syscall # argumento # llamada # resultado # llamada para # imprimir un int ... factorial: li li bucle: bgt mul addi b fin: move jr Estructura de Computadores $s1, 1 #s1 para r $s0, 1 #s0 para i $s0, $a0, fin $s1, $s1, $s0 $s0, $s0, 1 bucle $v0, $s1 #resultado $ra 40 Ejemplo 41 (4) Se analizan los registros que se modifican int factorial(int x) { int i; int r=1; for (i=1;i<=x;i++) { r*=i; } return r; } factorial: li li bucle: bgt mul addi b fin: move jr $s1, 1 #s1 para r $s0, 1 #s0 para i $s0, $a0, fin $s1, $s1, $s0 $s0, $s0, 1 bucle $v0, $s1 #resultado $ra n La función factorial trabaja (modifica) con los registros $s0, $s1 n Si estos registros se modifican dentro de la función, podría afectar a la función que realizó la llamada (la función main) n Por tanto, la función factorial debe guardar el valor de estos registros en la pila al principio y restaurarlos al final ARCOS Estructura de Computadores 41 Ejemplo 42 (5) Se guardan los registros en la pila int factorial(int x) { int i; int r=1; for (i=1;i<=x;i++) { r*=i; } return r; } factorial: addu sw sw li li bucle: bgt mul addi b fin: move lw lw addu jr $sp, $sp, -8 $s0, 4($sp) $s1, ($sp) $s1, 1 #s1 para r $s0, 1 #s0 para i $s0, $a0, fin $s1, $s1, $s0 $s0, $s0, 1 bucle $v0, $s1 #resultado $s1, ($sp) $s0, 4($sp) $sp, $sp, 8 $ra No es necesario guardar $ra. La rutina factorial es terminal Se guarda en la pila $s0 y $s1 porque se modifican Si se hubiera utilizado $t0 y $t1 no habría hecho falta hacerlo ARCOS Estructura de Computadores 42 Ejemplo 2 43 int main() { int z; int f1 (int a, int b) { int r; r = a + a + f2(b); return r; z=f1(5, 2); print_int(z); } } int f2(int c) { int s; s = c * c * c; return s; } ARCOS Estructura de Computadores 43 Ejemplo 2. Invocación 44 int main() { int z; li $a0, 5 li $a1, 2 jal f1 move $a0, $v0 li $v0, 1 syscall z=f1(5, 2); print_int(z); # # # # primer argumento segundo argumento llamada resultado # llamada para # imprimir un int } Los parámetros se pasan en $a0 y $a1 El resultado se devuelve en $v0 ARCOS Estructura de Computadores 44 Ejemplo 2. Cuerpo de f1 45 int f1 (int a, int b) { int r; r = a + a + f2(b); return r; f1: add $s0, $a0, $a0 move jal add $a0, $a1 f2 $v0, $s0, $v0 jr $ra } int f2(int c) { int s; s = c * c * c; return s; } ARCOS Estructura de Computadores 45 46 Ejemplo 2. Se analizan los registros que se modifican en f1 int f1 (int a, int b) { int r; r = a + a + f2(b); return r; f1: add $s0, $a0, $a0 move jal add $a0, $a1 f2 $v0, $s0, $v0 jr $ra } int f2(int c) { int s; f1 modifica $s0 y $ra, por lo tanto se guardan en la pila El registro $ra se modifica en la instrucción jal f2 El registro $a0 se modifica al pasar el argumento a f2, pero por convenio la función f1 no tiene porque guardarlo en la pila s = c * c * c; return s; } ARCOS Estructura de Computadores 46 47 Ejemplo 2. Cuerpo de f1 guardando en la pila los registros que se modifican int f1 (int a, int b) { int r; f1: addu sw sw $sp, $sp, -8 $s0, 8($sp) $ra, ($sp) add $s0, $a0, $a0 } move jal add $a0, $a1 f2 $v0, $s0, $v0 int f2(int c) { int s; lw lw addu $ra, ($sp) $s0, 8($sp) $sp, $sp, 8 jr $ra r = a + a + f2(b); return r; s = c * c * c; return s; } ARCOS Estructura de Computadores 47 Ejemplo 2. Cuerpo de f2 48 int f1 (int a, int b) { int r; r = a + a + f2(b); return r; } int f2(int c) { int s; s = c * c * c; return s; f2: mul $t0, $a0, $a0 mul $t0, $t0, $a0 jr $ra La función f2 no modifica el registro $ra porque no llama a ninguna otra función El registro $t0 no es necesario guardarlo porque no se ha de preservar su valor según convenio } ARCOS Estructura de Computadores 48 Convención en el uso de los registros en el MIPS Registro Uso Preservar el valor $v0-$v1 Resultados No $a0..$a3 Argumentos No $t0..$t9 Temporales No $s0..$s7 Salvados Si $sp Puntero de pila Si $fp Puntero marco de pila Si $ra Dirección de retorno Si ARCOS Estructura de Computadores 49 Tipos de subrutinas 50 n Subrutina terminal. q No invoca a ninguna otra subrutina. n Subrutina no terminal. q Invoca a alguna otra subrutina. ARCOS Estructura de Computadores 50 Activación de procedimientos Marco de pila n El marco de pila es el mecanismo que utiliza el compilador para activar los procedimientos (subrutinas) n El marco de pila lo construyen en la pila el procedimiento llamante y el llamado n Su manipulación se hace a través de dos registros: q $sp: puntero de pila, que apunta siempre a la cima de la pila q $fp: puntero de marco de pila, que marca la zona de la pila que pertenece al procedimiento llamado n El registro marco de pila ($fp) se utiliza en el procedimiento llamado para: q Acceder a los parámetros que se pasan en la pila q Acceder a las variables locales del procedimiento ARCOS Estructura de Computadores 51 Marco de pila n El marco de pila almacena: q Los parámetros introducidos por el procedimiento llamante en caso de ser necesarios q El registro marco de pila del procedimiento llamante (antiguo $fp) q Los registros guardados por la función (incluyen al registro $ra en caso de procedimientos no terminales) q Variables locales ARCOS Estructura de Computadores 52 Construcción del marco de pila Situación inicial antes de realizar la llamada a un procedimiento Direcciones bajas Crecimiento de la pila $sp Marco de pila eel procedimiento que realiza la llamada Direcciones altas ARCOS Estructura de Computadores 53 Construcción del marco de pila Direcciones bajas Antes de realizar la llamada el procedimiento llamante: n Deja los parámetros en $ai n El resto de parámetros en la pila Crecimiento de la pila $sp Parámetros del llamante Marco de pila Del procedimiento Que realiza la llamada Direcciones altas ARCOS Estructura de Computadores 54 Construcción del marco de pila Se realiza la llamada: n jal $sp Parámetros del llamante Marco de pila Del procedimiento Que realiza la llamada ARCOS Estructura de Computadores Espacio reservado por el procedimiento que realiza la llamada n También se puede incluir espacio para registros que se quieran preservar ($ai, $ti) 55 Construcción del marco de pila El procedimiento llamado guarda el registro $fp en la pila n Fija $fp al valor donde está almacenado el $fp anterior n $fp $sp $fp antiguo Parámetros del llamante Marco de pila Del procedimiento Que realiza la llamada ARCOS Estructura de Computadores Espacio reservado por el procedimiento que realiza la llamada n También se puede incluir espacio para registros que se quieran preservar ($ai, $ti) 56 Construcción del marco de pila Almacena el contenido de los registros cuyo valor haya que preservar ($si, $ra) $sp Registros guardados $fp por el llamado $fp antiguo Parámetros del llamante Marco de pila Del procedimiento Que realiza la llamada ARCOS Estructura de Computadores Espacio reservado por el procedimiento que realiza la llamada n También se puede incluir espacio para registros que se quieran preservar ($ai, $ti) 57 Construcción del marco de pila $sp Se deja espacio para las variables locales definidas en el procedimiento llamado Variables locales del procedimiento llamado Registros guardados $fp por el llamado $fp antiguo Parámetros del llamante Marco de pila Del procedimiento Que realiza la llamada ARCOS Estructura de Computadores Espacio reservado por el procedimiento que realiza la llamada n También se puede incluir espacio para registros que se quieran preservar ($ai, $ti) 58 Marco de pila $sp Variables locales del procedimiento llamado Marco de pila del procedimiento Registros guardados $fp Espacio reservado por el procedimiento llamado por el llamado $fp antiguo Parámetros del llamante ARCOS Estructura de Computadores Espacio reservado por el procedimiento que realiza la llamada 59 Marco de pila $sp Direcciones bajas Variables locales del procedimiento llamado Marco de pila del procedimiento Registros guardados $fp por el llamado $fp antiguo Parámetros del llamante El procedimiento llamado utiliza el registro $fp para acceder: n A los parámetros del llamente n Desplazamientos positivos n A las variables locales: n Desplazamientos negativos Direcciones altas ARCOS Estructura de Computadores 60 Acceso a parámetros y variables locales usando el marco de pila Direcciones bajas int f (int n1, n2, n3, n4, n5, n6) { int v[4]; int k; for (k= 0; k <3; k++) v[i] = n1+n2+n3+n4+n5+n6; } Crecimiento return (v[1]); de la pila Si se realiza una llamada a f( ) $sp Direcciones altas ARCOS Estructura de Computadores 61 Acceso a parámetros y variables locales usando el marco de pila Direcciones bajas int f (int n1, n2, n3, n4, n5, n6) { int v[4]; int k; for (k= 0; k <3; k++) v[i] = n1+n2+n3+n4+n5+n6; } Crecimiento return (v[1]); de la pila $sp n Los parámetros n1, n2, n3 y n4 Argumento n5 se pasan: q En $a0, $a1, $a2, $a3 n Los parámetros n5, n6 se pasan: q En la pila Argumento n6 ARCOS Estructura de Computadores Direcciones altas 62 Acceso a parámetros y variables locales usando el marco de pila Direcciones bajas int f (int n1, n2, n3, n4, n5, n6) { int v[4]; int k; for (k= 0; k <3; k++) v[i] = n1+n2+n3+n4+n5+n6; } return (v[1]); $sp Crecimiento $fp de la pila $fp antiguo n Una vez invocada la función, f Argumento n5 debe q Guardar una copia de $fp q Guardar una copia de los registros a preservar Argumento n6 ARCOS Estructura de Computadores Direcciones altas 63 Acceso a parámetros y variables locales usando el marco de pila int f (int n1, n2, n3, n4, n5, n6) { int v[4]; int k; $sp v[0] v[1] for (k= 0; k <3; k++) v[i] = n1+n2+n3+n4+n5+n6; } return (v[1]); Direcciones bajas v[2] $fp v[3] Crecimiento de la pila $fp antiguo n A continuación, f debe reservar en el marco Argumento n5 de pila espacio para las variables locales que no quepan en registros (en este ejemplo v) n Para este ejemplo se ha considerado que f no modifica ningún registro Argumento n6 Direcciones altas ARCOS Estructura de Computadores 64 Acceso a parámetros y variables locales usando el marco de pila int f (int n1, n2, n3, n4, n5, n6) { int v[4]; int k; $sp v[0] v[1] for (k= 0; k <3; k++) v[i] = n1+n2+n3+n4+n5+n6; } n n n n n Direcciones bajas v[2] $fp return (v[1]); v[3] Crecimiento de la pila $fp antiguo El valor de n1 está en $a0 El valor de n5 está en 4($fp) El valor de n6 está en 8($fp) El valor de v[3] está en -4($fp) El valor de v[0] está en -16($fp) ARCOS Estructura de Computadores Argumento n5 Argumento n6 Direcciones altas 65 Código para realizar la llamada a f(int n1, n2, n3, n4, n5, n6) Para la llamada: f(3, 4, 23, 12, 6, 7); li li li li addu li sw li sw jal ARCOS $a0, $a1, $a2, $a3, $sp, $t0, $t0, $t0, $t0, f 3 4 23 12 $sp, -8 6 0($sp) 7 4($sp) Los cuatro primeros en registros $ai El resto en la pila Estructura de Computadores 66 Código de la función f(int n1, n2, n3, n4, n5, n6) int f (int n1, n2, n3, n4, n5, n6) { int v[4]; int k; f: for (k= 0; k <3; k++) v[i] = n1+n2+n3+n4+n5+n6; } return (v[1]); ARCOS Estructura de Computadores 67 Código de la función f(int n1, n2, n3, n4, n5, n6) int f (int n1, n2, n3, n4, n5, n6) { int v[4]; int k; f: addu sw $sp, $sp, -4 $fp, ($sp) for (k= 0; k <3; k++) v[i] = n1+n2+n3+n4+n5+n6; } return (v[1]); Se guarda el valor de $fp ($fp antiguo) ARCOS Estructura de Computadores 68 Código de la función f(int n1, n2, n3, n4, n5, n6) int f (int n1, n2, n3, n4, n5, n6) { int v[4]; int k; f: addu sw move $sp, $sp, -4 $fp, ($sp) $fp, $sp for (k= 0; k <3; k++) v[i] = n1+n2+n3+n4+n5+n6; } return (v[1]); Se fija $fp a la posición donde está guardado el actual $fp ARCOS Estructura de Computadores 69 Código de la función f(int n1, n2, n3, n4, n5, n6) int f (int n1, n2, n3, n4, n5, n6) { int v[4]; int k; f: addu sw move addu $sp, $fp, $fp, $sp, $sp, -4 ($sp) $sp $sp, -16 for (k= 0; k <3; k++) v[i] = n1+n2+n3+n4+n5+n6; } return (v[1]); Se deja hueco para el vector v (16 bytes para 4 elementos de tipo int) ARCOS Estructura de Computadores 70 Código de la función f(int n1, n2, n3, n4, n5, n6) int f (int n1, n2, n3, n4, n5, n6) { int v[4]; int k; f: for (k= 0; k <3; k++) v[i] = n1+n2+n3+n4+n5+n6; } return (v[1]); addu sw move addu add add add lw add lw add $sp, $fp, $fp, $sp, $t0, $t0, $t0, $t1, $t0, $t1, $t0, $sp, -4 ($sp) $sp $sp, -16 $a0, $a1 $t0, $a2 $t0, $a3 4($fp) $t0, $t1 8($fp) $t0, $t1 Se calcula la suma n1+n2+n3+n4+n5+n6 ARCOS Estructura de Computadores 71 Código de la función f(int n1, n2, n3, n4, n5, n6) f: int f (int n1, n2, n3, n4, n5, n6) { int v[4]; int k; for (k= 0; k <3; k++) v[i] = n1+n2+n3+n4+n5+n6; } return (v[1]); Bucle ARCOS bucle: Estructura de Computadores addu sw move addu add add add lw add lw add li move addi li bgt sw addi addi b $sp, $sp, -4 $fp, ($sp) $fp, $sp $sp, $sp, -16 $t0, $a0, $a1 $t0, $t0, $a2 $t0, $t0, $a3 $t1, 4($fp) $t0, $t0, $t1 $t1, 8($fp) $t0, $t0, $t1 $t1, 0 # indice $t2, $fp $t2, $t2, -16 # desplaz. $t3, 3 $t1, $t3, fin $t0, ($t2) $t2, $t2, 4 $t1, $t1, 1 bucle 72 Código de la función f(int n1, n2, n3, n4, n5, n6) f: int f (int n1, n2, n3, n4, n5, n6) { int v[4]; int k; for (k= 0; k <3; k++) v[i] = n1+n2+n3+n4+n5+n6; } return (v[1]); bucle: fin: addu sw move addu add add add lw add lw add li move addi li bgt sw addi addi b $sp, $sp, -4 $fp, ($sp) $fp, $sp $sp, $sp, -16 $t0, $a0, $a1 $t0, $t0, $a2 $t0, $t0, $a3 $t1, 4($fp) $t0, $t0, $t1 $t1, 8($fp) $t0, $t0, $t1 $t1, 0 # indice $t2, $fp $t2, $t2, -16 # desplaz. $t3, 3 $t1, $t3, fin $t0, ($t2) $t2, $t2, 4 $t1, $t1, 1 bucle lw $v0, -12($fp) Preparar el valor a retornar en $v0 ARCOS Estructura de Computadores 73 Código de la función f(int n1, n2, n3, n4, n5, n6) f: int f (int n1, n2, n3, n4, n5, n6) { int v[4]; int k; for (k= 0; k <3; k++) v[i] = n1+n2+n3+n4+n5+n6; } return (v[1]); bucle: fin: Se restaura el valor de $fp ARCOS Estructura de Computadores addu sw move addu add add add lw add lw add li move addi li bgt sw addi addi b $sp, $sp, -4 $fp, ($sp) $fp, $sp $sp, $sp, -16 $t0, $a0, $a1 $t0, $t0, $a2 $t0, $t0, $a3 $t1, 4($fp) $t0, $t0, $t1 $t1, 8($fp) $t0, $t0, $t1 $t1, 0 # indice $t2, $fp $t2, $t2, -16 # desplaz. $t3, 3 $t1, $t3, fin $t0, ($t2) $t2, $t2, 4 $t1, $t1, 1 bucle lw lw $v0, -12($fp) $fp, ($fp) 74 Código de la función f(int n1, n2, n3, n4, n5, n6) f: int f (int n1, n2, n3, n4, n5, n6) { int v[4]; int k; for (k= 0; k <3; k++) v[i] = n1+n2+n3+n4+n5+n6; } return (v[1]); bucle: fin: Se restaura la pila y se retorna ARCOS Estructura de Computadores addu sw move addu add add add lw add lw add li move addi li bgt sw addi addi b $sp, $sp, -4 $fp, ($sp) $fp, $sp $sp, $sp, -16 $t0, $a0, $a1 $t0, $t0, $a2 $t0, $t0, $a3 $t1, 4($fp) $t0, $t0, $t1 $t1, 8($fp) $t0, $t0, $t1 $t1, 0 # indice $t2, $fp $t2, $t2, -16 # desplaz. $t3, 3 $t1, $t3, fin $t0, ($t2) $t2, $t2, 4 $t1, $t1, 1 bucle lw lw addu jr $v0, -12($fp) $fp, ($fp) $sp, $sp, 20 $ra 75 Código posterior a la llamada a f(int n1, n2, n3, n4, n5, n6) Para la llamada: f(3, 4, 23, 12, 6, 7); li li li li addu li sw li sw jal $a0, $a1, $a2, $a3, $sp, $t0, $t0, $t0, $t0, f 3 4 23 12 $sp, -8 6 0($sp) 7 4($sp) addu $sp, $sp, 8 move $a0, $v0 li $v0, 1 syscall ARCOS Los cuatro primeros en registros $ai El resto en la pila Deja el puntero de pila en el estado anterior En $v0 está el valor devuelto: lo imprime Estructura de Computadores 76 Convenio de paso de parámetros 77 n Convenio que describe: q Uso del banco de registros generales. q Uso del banco de registros FPU. q Uso de la pila. q Afecta a código llamante y código llamado. n Distintos compiladores usan distintos convenios. q ABI à Application Binary Interface. ARCOS Estructura de Computadores 77 Convención en el uso de los registros en el MIPS Registro Uso Preservar el valor $v0-$v1 Resultados No $a0..$a3 Argumentos No $t0..$t9 Temporales No $s0..$s7 Salvados Si $sp Puntero de pila Si $fp Puntero marco de pila Si $ra Dirección de retorno Si ARCOS Estructura de Computadores 78 Subrutinas paso a paso 79 Subrutina que hace la llamada Subrutina llamada Salvaguarda de registros que no quiera que modifique la subrutina llamada Paso de parámetros Llamada a subrutina Reserva del marco de pila Salvaguarda de registros Ejecución de subrutina Restauración de valores guardados Liberación de marco de pila Salida de subrutina Restauración de registros guardados ARCOS Estructura de Computadores 79 Ejercicio Considere una función denominada func que recibe tres parámetros de tipo entero y devuelve un resultado de tipo entero, y considere el siguiente fragmento del segmento de datos: .data a: .word 5 b: .word 7 c: .word 9 .text Indique el código necesario para poder llamar a la función anterior pasando como parámetros los valores de las posiciones de memoria a, b y c. Una vez llamada a la función deberá imprimirse el valor que devuelve la función. ARCOS Estructura de Computadores 80 81 Salvaguarda de registros Subrutina llamante Registros $t n Una subrutina puede modificar libremente los registros $t. q Antes de invocar una subrutina se deben guardar los registros $t de los que se quiera preservar su valor. pila subu $sp, $sp, 8 sw $t0,($sp) sw $t1, 4($sp) jal funcion lw $t1, 4($sp) lw $t0, ($sp) addu $sp, $sp, 8 ARCOS Estructura de Computadores 81 82 Paso de parámetros Subrutina llamante n Los primeros parámetros se pasan mediante registros q $a0, $a1, $a2, $a3 q $f12, $f14 (coma flotante) q Resto de parámetros a través de pila ARCOS Estructura de Computadores 82 Paso de 2 parámetros Banco de registros 83 $a0 $a1 $a2 $a3 Registros $t Parámetro Parámetro Parámetro Parámetro 1 2 3 4 pila li $a0, 5 li $a1, 8 // param 1 // param 2 jal func addu $sp, $sp, 16 ARCOS Estructura de Computadores 83 Paso de 6 parámetros Banco de registros 84 $a0 $a1 $a2 $a3 Parámetro 5 Parámetro 6 Parámetro Parámetro Parámetro Parámetro 1 2 3 4 Registros $t li li li li pila $a0, $a1, $a2, $a3, 5 8 7 9 // // // // param param param param 1 2 3 4 subu $sp, $sp, 8 li $t0, 10 // param 6 sw $t0, 4($sp) li $t0, 7 s2 $t0, ($sp) // param 5 jal func addu $sp, $sp, 8 ARCOS Estructura de Computadores 84 85 Llamada a subrutina Subrutina llamante n Instrucción de salto “and link” q jal etiqueta q bal etiqueta q bltzal $reg, etiqueta q bgezal $reg, etiqueta q jalr $reg q jalr $reg, $reg ARCOS Estructura de Computadores 85 86 Reserva del marco de pila Subrutina llamada n La subrutina llamada guarda en la pila El registro $fp antiguo q Los registros guardados por la función n Los registros $s que vaya a modificar. n El registro $ra en las subrutinas no terminales. q Variables locales q n Para reservar el marco de pila, restar su tamaño al puntero de pila. ARCOS Estructura de Computadores 86 Ejecución de la subrutina 87 n La subrutina deja los valores de retorno en: q Normalmente los registros $v0 y $v1 q Para coma flotante $f0 y $f2. q ARCOS Si hace falta más espacio se deja información en la pila. Estructura de Computadores 87 Al final 88 n Subrutina llamada: q Restauración de valores guardados n Se restauran los valores que se guardaron q Liberación del marco de pila. n Se suma a $sp el tamaño del marco de pila q $sp = $fp n Se restaura el valor de $fp q Se vuelve a la subrutina llamante. n jr $ra n Subrutina llamante: q Se ARCOS restauran los valores guardados en la pila Estructura de Computadores 88 Ejemplo: factorial int factorial ( int a ) { if (a < 2) then return 1 ; return a * factorial(a-1) ; } factorial(a=4) (a < 2) ? 6 * 4 factorial(a=3) (a < 2) ? 2 * 3 void main () { int resultado ; resultado=factorial(4) ; printf(“f(4)=%d”,resultado); } ARCOS factorial(a=2) (a < 2) ? 1 * 2 factorial(a=1) (a < 2) ? Estructura de Computadores 89 Ejemplo: factorial Direcciones bajas Justo antes de la llamada $sp Direcciones altas ARCOS @ UC3M 90 Ejemplo: factorial factorial: Direcciones bajas # frame stack subu $sp $sp 12 sw $ra 4($sp) sw $fp 8($sp) addu $fp $sp 8 $sp $fp $ra $fp (antiguo) Direcciones altas ARCOS @ UC3M 91 Ejemplo: factorial factorial: Direcciones bajas # frame stack subu $sp $sp 12 sw $ra 4($sp) sw $fp 8($sp) addu $fp $sp 8 bge $a0 2 b_else li $v0 1 b b_efs b_else: sw $a0 -8($fp) addi $a0 $a0 -1 jal factorial lw $v1 -8($fp) mul $v0 $v0 $v1 $sp $a0 $fp $ra $fp (antiguo) Direcciones altas ARCOS @ UC3M 92 Ejemplo: factorial factorial: Direcciones bajas # frame stack subu $sp $sp 12 sw $ra 4($sp) sw $fp 8($sp) addu $fp $sp 8 bge $a0 2 b_else li $v0 1 b b_efs b_else: sw $a0 -8($fp) addi $a0 $a0 -1 jal factorial lw $v1 -8($fp) mul $v0 $v0 $v1 # end frame stack b_efs: lw $ra 4($sp) lw $fp ($fp) addu $sp $sp 12 jr $ra $a0 $ra $sp $fp (antiguo) Direcciones altas ARCOS @ UC3M 93 Traducción y ejecución de programas n Elementos que intervienen en la traducción y ejecución de un programa: q Compilador q Ensamblador q Enlazador q Cargador ARCOS Estructura de Computadores 94 Código compilado frente a interpretado n Código compilado: Los programas son traducidos a código máquina de un computador n El código es ejecutado directamente por el computador n Generalmente más eficiente n Código interpretado: q Un interprete es un programa que ejecuta otros programas q Un interprete ejecuta un conjunto de instrucciones independientes de la máquina. Las instrucciones son ejecutadas por un programa q Ejemplo: Java es traducido a un byte code que es ejecutado por un interprete (Java Virtual Machine) q Generalmente es más fácil escribir un interprete. Mayor portabilidad q ARCOS Estructura de Computadores 95 Etapas en la traducción y ejecución de un programa (programa en C) Programa C Compilador Programa en ensambaldor Ensamblador Objeto: módulo en lenguaje máquina Objeto: bibliotecas en lenguaje máquina Enlazador Ejecutable: programa en lenguaje máquina Cargador ARCOS Estructura de Computadores Memoria 96 Compilador n n n n Entrada: lenguaje de alto nivel (C, C++, …) Salida: código en lenguaje ensamblador Puede contener pseudoinstrucciones Una pseudoinstrucción es una instrucción que entiende el ensamblador pero que no tiene correspondencia directa con una instrucción en lenguaje máquina q move $t1, $t2 ⇒ or $t1, $t2, $zero ARCOS Estructura de Computadores 97 Ensamblador n Entrada: código en lenguaje ensamblador n Salida: Código objeto escrito en lenguaje máquina n En ensamblador convierte las pseudoinstrucciones a instrucciones máquina n Analiza las sentencias en ensamblador de forma independiente, sentencia a sentencia n El ensamblador produce un fichero objeto (.o) ARCOS Estructura de Computadores 98 Análisis de sentencias en ensamblador n Se comprueba si la instrucción es correcta (código de operación, operandos, direccionamientos válidos, …) n Se comprueba si la sentencia tiene etiqueta. Si la tiene comprueba que el código simbólico no está repetido y le asigna el valor correspondiente a la posición de memoria que habrá de ocupar la instrucción o el dato. n Construye una tabla de símbolos con todas las etiquetas simbólicas q En una primera fase o pasada se determinan todos los valores que no conllevan referencias adelantadas q En una segunda fase o pasada se resuelven aquellas etiquetas que han quedado pendientes ARCOS Estructura de Computadores 99 Formato de un fichero objeto n Cabecera del fichero. Describe el tamaño y posición de los elementos dentro del fichero n Segmento de texto: contiene el código máquina n Segmento de datos: contiene los datos de las variables globales n Información de reubicación: identifica instrucciones o palabras de datos que dependen de una dirección absoluta cuando el programa se cargue en memoria n Cualquier etiqueta de j or jal (internas o externas) n Direcciones de datos n Tabla de símbolos: etiquetas no definidas en este módulo (referencias externas) n Información de depuración. Permite asociar instrucciones máquina con código C e interpretar las estructuras de datos ARCOS Estructura de Computadores 100 Enlazador n Entrada: ficheros en código objeto n Salida: Código ejecutable n Combina varios archivos objeto (.o) en un único fichero ejecutable n Resuelve todas las referencias (instrucciones de salto y direcciones de datos) n En enlazador asume que la primera palabra del segmento de texto está en la dirección 0x00000000 n Permite la compilación separada de ficheros q El cambio en un fichero no implica recompilar todo el programa completo q Permite el uso de funciones de biblioteca (.a) ARCOS Estructura de Computadores 101 Enlazador .o file 1 text 1 a.out Relocated text 1 data 1 info 1 Linker Relocated text 2 Relocated data 1 .o file 2 text 2 Relocated data 2 data 2 info 2 ARCOS Estructura de Computadores 102 Formato de un fichero ejecutable n Cabecera del fichero. Describe el tamaño y posición de los elementos dentro del fichero. Incluye la dirección de inio del programa n Segmento de texto: contiene el código máquina n Segmento de datos: contiene los datos de las variables globales con valor inicial n Información de reubicación: en caso de utilizar bibliotecas dinámicas ARCOS Estructura de Computadores 103 Cargador n Lee un fichero ejecutable (a.out) y lo carga en memoria Memoria Principal Sistema Operativo Disco instrucciones Programa en ejecucion datos Fichero ejecutable pila ARCOS Estructura de Computadores 104 Cargador n Forma parte del sistema operativo n Lee la cabecera del ejecutable para determinar el tamaño de n n n n los segmentos de texto y datos Crea un nuevo espacio de direcciones en memoria para ubicar el segmento de texto, datos y pila Copia las instrucciones y los datos con valor inicial del fichero ejecutable (disco) a memoria Copia los argumentos que se pasan al programa en la pila Inicializa los registros. Fija el PC y el SP a sus posiciones ARCOS Estructura de Computadores 105 Bibliotecas n Una biblioteca es una colección de objetos normalmente relacionados entre sí n Los módulos objetos de los programas pueden incluir referencias a símbolos definidos en alguno de los objetos de una biblioteca (funciones o variables exportadas) n Las bibliotecas del sistema son un conjunto de bibliotecas predefinidas que ofrecen servicios a las aplicaciones n Tipos: q Bibliotecas estáticas: se enlazan con los ficheros objeto para producir un fichero ejecutable que incluye todas las referencias resueltas. Un cambio en la biblioteca implica volver a enlazar y generar el ejecutable q Bibliotecas dinámicas (DLL, dynamically linked library) ARCOS Estructura de Computadores 106 Bibliotecas dinámicas n Las rutinas de las bibliotecas no se enlazan en el archivo ejecutable y no se cargan hasta que el programa se ejecuta n El programa incluye información para la localización de las bibliotecas y la actualización de las referencias externas durante la ejecución n Ventajas: q Da lugar a ejecutables más pequeños. q Solo se carga de la biblioteca aquello que se utiliza durante la ejecución. q El cambio en una biblioteca no afecta al ejecutable. No se necesita volver a generar un nuevo ejecutable. ARCOS Estructura de Computadores 107 Ejemplo C ⇒ ASM ⇒ Οbj ⇒ Exe ⇒ Ejecución Programa C: ejemplo.c #include <stdio.h> int main (int argc, char *argv[]) { int i, sum = 0; for (i = 1; i <= 10; i++) sum = sum + i + i; printf (“La suma 1 + ... +10 es %d\n", sum); } printf(): función de biblioteca en libc.a ARCOS Estructura de Computadores 108 Compilación .text .align 2 .globl main main: subu $sp,$sp,24 sw $ra, 20($sp) sw $a0, 4($sp) sw $a1, 8($sp) li $t0, 0 li $t1, 0 bucle: bgt $t0, 10, fin add $t1, $t1, $t0 addi $t0, $t0, 1 b bucle ARCOS fin: la $a0, str li $a1, $t1 jal printf move $v0, $0 lw $ra, 20($sp) lw $a0, 4($sp) lw $a1, 8($sp) addiu $sp,$sp,24 jr $ra .data .align 0 str: .asciiz " La suma 1 + ... +10 es %d\n " Estructura de Computadores 109 Compilación .text .align 2 .globl main main: subu $sp,$sp,24 sw $ra, 20($sp) sw $a0, 4($sp) sw $a1, 8($sp) li $t0, 0 li $t1, 0 bucle: bgt $t0, 10, fin add $t1, $t1, $t0 addi $t0, $t0, 1 b bucle ARCOS fin: la $a0, str li $a1, $t1 jal printf move $v0, $0 lw $ra, 20($sp) lw $a0, 4($sp) lw $a1, 8($sp) addiu $sp,$sp,24 jr $ra .data 7 pseudo.align 0 instructiones .data: str:.asciiz " La suma 1 + ... +10 es %d\n " Estructura de Computadores 110 Compilación Eliminación de pseudoinstrucciones .text .align 2 .globl main main: addiu $29,$29,-24 sw $31, 20($29) sw $4, 4($29) sw $5, 8($29) ori $8, $0, 0 ori $9, $0, 0 bucle: slti $1, $8, 11 beq $1, $0, fin add $9, $9, $8 addi $8, $8, 1 bgez $0, bucle ARCOS fin: lui $4, l.str ori $4, $4, r.str addu $4, $0, $9 jal printf addu $2, $0, $0 lw $31, 20($29) lw $4, 4($29) lw $5, 8($29) addiu $29,$29,24 jr $31 Estructura de Computadores 111 Compilación Asignación de direcciones 00 04 08 0c 10 14 18 1c 20 24 28 ARCOS addiu $29,$29,-24 sw $31, 20($29) sw $4, 4($29) sw $5, 8($29) ori $8, $0, 0 ori $9, $0, 0 slti $1, $8, 11 beq $1, $0, fin add $9, $9, $8 addi $8, $8, 1 bgez $0, bucle 2c 30 34 38 3c 40 44 48 4c 50 Estructura de Computadores lui $4, l.str ori $4, $4, r.str addu $4, $0, $9 jal printf addu $2, $0, $0 lw $31, 20($29) lw $4, 4($29) lw $5, 8($29) addiu $29,$29,24 jr $31 112 Compilación Creación de la tabla de símbolos y de reubicación n Tabla de símbolos Etiqueta main: bucle: str: dirección (en modulo) tipo 0x00000000 global text 0x0000001c local text 0x00000000 local data n Información de reubicación Direccíón 0x0000002c 0x00000030 0x00000038 ARCOS tipo Instr. lui ori jal Estructura de Computadores Dependencia l.str r.str printf 113 Compilación Resolver etiquetas relativas a PC 00 04 08 0c 10 14 18 1c 20 24 28 ARCOS addiu $29,$29,-24 sw $31, 20($29) sw $4, 4($29) sw $5, 8($29) ori $8, $0, 0 ori $9, $0, 0 slti $1, $8, 11 beq $1, $0, 3 add $9, $9, $8 addi $8, $8, 1 bgez $0, -4 2c 30 34 38 3c 40 44 48 4c 50 Estructura de Computadores lui $4, l.str ori $4, $4, r.str addu $4, $0, $9 jal printf addu $2, $0, $0 lw $31, 20($29) lw $4, 4($29) lw $5, 8($29) addiu $29,$29,24 jr $31 114 Segmento de texto en el fichero objeto 0x000000 0x000004 0x000008 0x00000c 0x000010 0x000014 0x000018 0x00001C 0x000020 0x000024 0x000028 0x00002C 0x000030 0x000034 0x000038 0x00003c 0x000040 0x000044 0x000048 0x00004c 0x000050 ARCOS 00100111101111011111111111101000 10101111101111110000000000010100 10101111101001000000000000000100 10101111101001010000000000001000 10001101000000000000000000000000 10101101001000000000000000011100 00101000001010000000000000001011 00010000001000000000000000000011 00000001001010000100100000100000 00100001000010000000000000000001 00000100000000001111111111111100 00111100000001000000000000000000 00110100100001000000000000000000 00000001001001000000000000100001 00001100000000000000000000000000 00000000000000000001000001000001 10001111101111110000000000010100 10001111101001000000000000000100 10001111101001010000000000001000 00000011111000000000000000011000 00000000000000001110100000001000 Estructura de Computadores 115 Enlazado n Combinar ejemplo.o y libc.a n Crear las direcciones de memoria absolutas n Modificar y mezclar las tablas de símbolos y de reubicación n Symbol Table q Label Address main: 0x00000000 loop: 0x0000001c str: 0x10000430 printf: 0x000003b0 … n Relocation Information q Address Instr. Type Dependency 0x0000002c lui l.str 0x00000030 ori r.str 0x00000038 jal printf ARCOS Estructura de Computadores … 116 Enlazado Resolver las direcciones 00 04 08 0c 10 14 18 1c 20 24 28 ARCOS addiu $29,$29,-24 sw $31, 20($29) sw $4, 4($29) sw $5, 8($29) ori $8, $0, 0 ori $9, $0, 0 slti $1, $8, 11 beq $1, $0, 3 add $9, $9, $8 addi $8, $8, 1 bgez $0, -4 2c 30 34 38 3c 40 44 48 4c 50 Estructura de Computadores lui $4, 4096 ori $4, $4, 1072 addu $4, $0, $9 jal 812 addu $2, $0, $0 lw $31, 20($29) lw $4, 4($29) lw $5, 8($29) addiu $29,$29,24 jr $31 117 Enlazado n Generación del fichero ejecutable q q q ARCOS Único segmento de texto Único segmento de datos Cabecera con información sobre las secciones Estructura de Computadores 118