Estructuras de Computadores I Tarea 02 02/99 1. Dada la
Transcrição
Estructuras de Computadores I Tarea 02 02/99 1. Dada la
Estructuras de Computadores I Tarea 02 02/99 1. Dada la secuencia de bits: 0011 0100 0101 0101 0100 0011 0100 0010 Qué representa, asumiendo que es: a. Un número entero en complemento dos. b. Fracción en complemento dos c. Un entero sin signo d. Un punto flotante precisión simple. e. Una instrucción MIPS (usar nombres simbólicos para los registros) Puntos b, c, d para más adelante. 2. Lazo en MIPS. Asuma que al inicio los registro que requieren estar inicializados, tienen valor 0, antes de ingresar al lazo. Suponga también que el lazo pueda ser ejecutado, al menos cinco veces, de tal forma que algunos registros podría requerir ser salvados (antes de invocar) y luego restaurados (después del retorno de la subrutina). Esto debido a que existe un llamado a una subrutina, en el medio del lazo, y que esta subrutina podría sobreescribir en alguno de los registros. Escribir el código para salvar y restaurar, para ello es preciso analizar cuidadosamente el código antes y después del "jal". Loop: add lw slt beq addi lw lw jal add lw add addi $t1, $t3, $s0 $a1, 4($t1) $t2, $0, $a1 $t2, $0, Exit $a0, $a0, 1 $a2, 0($s1) $a3, 8($sp) . . . HaceAlgo . . . $t4, $v0, $t4 $t5, 0($v1) $t4, $t5, $t4 $t3, $t3, -4 1 ELO311 Tarea 02 addi slti beq 02/99 $t0, $t0, -1 $t6, $t0, 5 $t6, $0, Loop Exit: 3. Ensamblar a mano, el siguiente código. Asumir el inicio de la zona de texto en 0x00400000. Comprobar los valores de los campos mediante el simulador. (El nombre main permite al simulador, con trap-handler, llamar al programa main.) main: Loop: End: sub addi lui ori andi slt bne sll j add jr $t0, $0, $0 $t1, $t0, 1 $t6, 0xffff $t6, $t6, 0xffff $t5, $t6, 0x5ca3 $t4, $t5, $t1 $t4, $0, End $t1, $t1, 1 Loop $v0, $t1, $0 $ra Expresar en hexadecimal. Obs. El simulador ensambla mal los direccionamientos de los branch. La forma correcta de efectuarlos es tomando la dirección de la instrucción siguiente al branch, y a esta dirección sumarle el número con signo establecido en el campo inmediato. Además considerar que el úmero es de instrucciones y no de bytes. Solución 1. 1. Dada la secuencia de bits: 00110100010101010100001101000010 Qué representa , asumiendo que es : a. Un número entero en complemento dos. Respuesta: En este caso, por comenzar con cero la secuencia,se trata de un numero entero positivo.Para llegar a conocer este número, primero pasamos la secuencia a su equivalente hexadecimal, para luego transformarlo a entero equivalente decimal; el procedimiento se muestra a continuación: 2 ELO311 Tarea 02 02/99 Secuencia: 0011 0100 0101 0101 0100 0011 0100 0010 Hexadecimal: 3 4 5 5 4 3 4 2 Decimal: 878003010 e. Una instrucción MIPS, (usando nombres simbólicos para los registros): Respuesta: Nos fijamos primero en los 6 primeros bits: 001101: correspnde al código de instrucción ori. Estamos entonces en el formato I . Los 5 bits siguientes, corresponden al registro rs: 00010: corresponde al registro $v0 Los siguientes 5 bits, son para el registro rt: 10101: corresponde al registro $s5. Los 16 bits siguientes, corresponden a la dirección inmediata, cuyo equivalente decimal , se incluye en la instrucción: 0100001101000010: su equivalente decimal es 17218, y su equivalente hexadecimal es: 4342 La instrucción entonces, es la que se muestra a continuación: Ori $s5,$v0,0x4342 Lo que se muestra a continuacion, es la estructura del formato I, especificamente para nuestro ejemplo: Nombre formato Ori I op rs rt 001101 00010 10101 13 2 21 dir. Inmediata 0100001101000010 17218 (decimal) 3 ELO311 Tarea 02 02/99 2.- En el programa existen algunos registros que como son temporales del lazo, deben ser guardados. Estos registros son : $t0, $t3, $t4. Además conviene guardar la información que está en el stack pointer y en el registro $ra, por si se modifican dentro de la subrutina. Hay registros auxiliares y otros que sirven para pasar los parámetros, que no se justifica guardarlos porque son parte de los valores que se alteran. .text .globl main main: Loop: add lw slt beq addi lw lw subu sw sw sw sw sw addu jal lw lw lw lw lw addu add lw add addi addi slti beq $t1, $t3, $s0 $a1, 4($t1) $t2, $0, $a1 $t2, $0, Exit $a0, $a0, 1 $a2, 0($s1) $a3, 8($sp) $sp,$sp,24 $ra,4($sp) $fp,8($sp) $t0,12($sp) $t3,16($sp) $t4,20($sp) $fp,$sp,24 HaceAlgo $ra,4($sp) $fp,8($sp) $t0,12($sp) $t3,16($sp) $t4,20($sp) $sp,$sp,24 $t4, $v0, $t4 $t5, 0($v1) $t4, $t5, $t4 $t3, $t3, -4 $t0, $t0, -1 $t6, $t0, 5 $t6, $0, Loop 4 ELO311 Tarea 02 02/99 3. Ensamblar a mano, el siguiente código. Asumir el inicio de la zona de texto en 0x00400000. Comprobar los valores de los campos mediante el simulador. (El nombre main permite al simulador, con trap-handler, llamar al programa main.) main: Loop: End: sub addi lui ori andi slt bne sll j add jr $t0, $0, $0 $t1, $t0, 1 $t6, 0xffff $t6, $t6, 0xffff $t5, $t6, 0x5ca3 $t4, $t5, $t1 $t4, $0, End $t1, $t1, 1 Loop $v0, $t1, $0 $ra Expresar en hexadecimal. Obs. El simulador ensambla mal los direccionamientos de los branch, sino se emplea el modi baremachine. La forma correcta de efectuarlos es tomando la dirección de la instrucción siguiente al branch, y a ésta dirección sumarle el número con signo establecido en el campo inmediato. Además considerar que el número es de instrucciones y no de bytes. Ensamblando a mano: 0x00004022 0x21090001 0x3c0effff 0x35ceffff 0x31cd5ca3 0x01a9602a 0x15800002 0x00094840 0x08100005 [0x01201020 0x03e00008 sub $t0, $0, $0 addi $t1, $t0, 1 lui $t6, 0xffff ori $t6, $t6, 0xffff andi $t5, $t6, 0x5ca3 slt $t4, $t5, $t1 bne $t4, $0, End sll $t1, $t1, 1 j Loop add $v0, $t1, $0 jr $ra Observando el simulador Spim una vez cargado el programa mostrado(sin trap-handler): [0x00400000] [0x00400004] [0x00400008] 0x00004022 sub $8, $0, $0 0x21090001 addi $9, $8, 0x3c0effff lui $14, -1 ; 3: sub ; 4: addi ; 5: lui $t0, $0, $0 $t1, $t0, 1 $t6, 0xffff 5 ELO311 Tarea 02 [0x0040000c] [0x00400010] [0x00400014] [0x00400018] [0x0040001c] [0x00400020] [0x00400024] [0x00400028] 02/99 0x35ceffff ori $14, $14, -1 ; 6: ori 0x31cd5ca3 andi $13, $14, 23715 ; 7: andi 0x01a9602a slt $12, $13, $9 ; 8: slt 0x15800003 bne $12, $0, 12; ;9: bne [End-0x00400018] 0x00094840 sll $9, $9, 1 ; 10: sll 0x08100005 j 0x00400014 [Loop] ; 11: j 0x01201020 add $2, $9, $0 ; 12: add 0x03e00008 jr $31 ; 13: jr $t6,$t6,0xffff $t5,$t6,0x5ca3 $t4, $t5, $t1 $t4, $0, End $t1, $t1, 1 Loop $v0, $t1, $0 $ra Se puede apreciar claramente el error que comete el simulador Spim ( lo que está marcado con rojo), siendo correcta la instrucción que fue ensamblada a mano y está marcada con verde. Solución 2. 1. Dada la secuencia de bits: 0011 0100 0101 0101 0100 0011 0100 0010 a) El número entero en complemento dos que representa es: (+) 2+4·16+3·256+4·163+5·164+5·165+4·166+3·167 = 878003010 El signo positivo lo da el bit más significativo, ya que es un cero. b) La instrucción MIPS que representa es: (se utilizó la tabla para ensamblar instrucciones del manual del programador) 001101 00010 10101 0100 0011 0100 0010 Los primeros 6 dígitos indican la operación: Los siguientes cinco corresponden a Fte1: Los siguientes cinco corresponden a Dst: Los restantes 16 corresponden a Inm16: ori $2 ($v0) $21 ($s5) 0x4342 = 17218 dec Si consideramos que la sintaxis para la instrucción ori es: ori Dst, Fte1, Inm16 , entonces llegamos a que la secuencia de bits en cuestión corresponde a la instrucción: ori $s5 , $v0 , 17218 2. Quisimos realizar una primera aproximación con los conocimientos obtenidos a la fecha. El desarrollo logrado es el siguiente: 6 ELO311 Tarea 02 02/99 Se entiende del enunciado que se desea hacer un programa que salve y otro que luego restaure ciertos registros. En particular t1, a1, t2, a0, a2, a3. Se supone que fP debe apuntar al inicio del segmento de datos en el stack, disponible a la función. Deseamos guardar seis registros. Como éstos son de 32 bits, necesitamos 6 palabras o equivalentemente 24 bytes. El stack crece hacia direcciones más bajas. Los códigos para salvar y para restaurar los registros son, respectivamente: Salvar: subre $sp, $sp, 24 sw $t1, 0($sp) sw $a1, 4($sp) sw $t2, 8($sp) sw $a0,12($sp) sw $a2, 16($sp) sw $a3, 20($sp) sw $fp, -4($sp) Restaurar: addi $sp , $fp, 4 lw $t1, 0($sp) lw $a1, 4($sp) lw $t2, 8($sp) lw $a0,12($sp) lw $a2, 16($sp) lw $a3, 20($sp) addre $sp, $sp, 24 7 ELO311 Tarea 02 02/99 3. Ensamblar a mano el siguiente código: main: Loop: End: sub addi lui ori andi slt bne sll j add jr $t0, $0, $0 $t1, $t0, 1 $t6, 0xffff $t6, $t6, 0xffff $t5, $t6, 0x5ca3 $t4, $t5, $t1 $t4, $0, End $t1, $t1, 1 Loop $v0, $t1, $0 $ra Utilizando el manual del programador, se ensamblaron las instrucciones y el código de máquina obtenido es el siguiente: [0x00400000] 000000 00000 00000 01000 00000 100010 0x 00004022 [0x00400004] 001000 01000 01001 0000 0000 0000 0001 0x 21090001 [0x00400008] 001111 00000 01110 1111 1111 1111 1111 0x 3c0effff [0x0040000c] 001101 01110 01110 1111 1111 1111 1111 0x 35ceffff [0x00400010] 001100 01110 01101 0101 1100 1010 0011 0x 31cd5ca3 [0x00400014] 000000 01101 01001 01100 00000 101010 0x 01a 9602 a [0x00400018] 000101 01100 00000 0000 0000 0000 0002 0x 15800002 [0x0040001c] 000000 00000 01001 01001 00001 000000 0x 00094840 [0x00400020] 000010 0000 0100 0000 0000 0000 0001 01 0x 08100005 [0x00400024] 000000 01001 00000 00010 00000 100000 0x 01201020 8 ELO311 Tarea 02 02/99 Los resultados obtenidos en el simulador son los siguientes: [0x00400000] [0x00400004] [0x00400008] [0x0040000c] [0x00400010] [0x00400014] [0x00400018] [0x0040001c] [0x00400020] 0x00004022 sub $8, $0, $0 ; 6: sub $t0, $0, $0 0x21090001 addi $9, $8, 1 ; 7: addi $t1, $t0, 1 0x3c0effff lui $14, -1 ; 8: lui $t6, 0xffff 0x35ceffff ori $14, $14, -1 ; 9: ori $t6, $t6, 0xffff 0x31cd5ca3 andi $13, $14, 23715 ; 10: andi $t5, $t6, 0x5ca3 0x01a9602a slt $12, $13, $9 ; 11: slt $t4, $t5, $t1 0x15800003 bne $12, $0, 12 [End-0x00400018]; 12: bne $t4, $0, End 0x00094840 sll $9, $9, 1 ; 13: sll $t1, $t1, 1 0x08100005 j 0x00400014 [Loop] ; 14: j Loop Puede notarse el error de direccionamiento cometido por el simulador (línea destacada). El ensamblaje correcto de esa instrucción branch es, como se observa en el desarrollo previo: 0x15800002. Esto se advirtió en clases y se debe a que el simulador considera a PC apuntando a una dirección incorrecta, si no se setea el modo bare-machine. Luego de esta línea se repiten cíclicamente las últimas 4 instrucciones (debido al salto). Para lograr tener en bitácora el resto de las instrucciones fue necesario simular una vez más sin el salto a Loop. El resultado fue el siguiente: [0x00400000] [0x00400008] [0x0040000c] [0x00400010] [0x00400014] [0x00400018] [0x0040001c] [0x00400020] [0x00400024] 0x00004022 sub $8, $0, $ ; 7: addi $t1, $t0, 1 0x3c0effff lui $14, -1 ; 8: lui $t6, 0xffff 0x35ceffff ori $14, $14, -1 ; 9: ori $t6, $t6, 0xffff 0x31cd5ca3 andi $13, $14, 23715 ; 10: andi $t5, $t6, 0x5ca3 0x01a9602a slt $12, $13, $9 ; 11: slt $t4, $t5, $t1 0x15800002 bne $12, $0, 12 [End-0x00400018]; 12: bne $t4, $0, End 0x00094840 sll $9, $9, 1 ; 13: sll $t1, $t1, 1 0x01201020 add $2, $9, $0 ; 15: add $v0, $t1, $0 0x03e00008 jr $31 ; 16: jr $ra Se advierte que en esta ocasión el direccionamiento se realiza correctamente. En todas las demás instrucciones el ensamblaje a mano concuerda con el obtenido en el simulador. 9 ELO311 Tarea 02 02/99 Solución 3. 1. Dada la secuencia de bits: 0011 0100 0101 0100 0011 0100 0010 Qué representa, asumiendo que es: a. Un número entero en complemento dos. b. Una instrucción MIPS (usar nombres simbólicos para los registros) a) Considerando la secuencia de 32 bits como un número en complemento dos debemos tomar en cuenta el primer bits (más significativo) como el signo. Debido a que dicho valor es un cero la secuencia representa un entero positivo, esto implica que (para este caso), los 31 bits menos significativos se consideran como un entero sin signo (en valor absoluto), dicho valor queda estructurado de la siguiente forma. Expresado en hexadecimal: 0 / 011 / 0100 / 0101 / 0101 / 0100 / 0011 / 0100 / 0010 + / 3 / 4 / 5 / 5 / 4 / 3 / 4 / 2 dicha secuencia equivale al = 0x34554342 Expresado en decimal = 878.003.010 b) Si consideramos la secuencia de 32 bits como una instrucción MIPS: 001101 / 00010 /10101 /0100001101000010 Observando los 6 primeros bits (los mas significativos), y compararlos con los bits de operación de las distintas instrucciones señaladas en el manual del programador MIPS, se concluye que dicha secuencia de bits de operación corresponde a la instrucción ori, esta instrucción utiliza el formato I para ser ensamblada,es decir: Transferencias: I Op 6 Rs 5 Rt 5 Inmediato 16 Op = 001101. Rs = 00010 que equivale al registro $2 = $v0 Rt = 10101 que equivale al registro $21 = $s5 Inmediato 16 = 0100001101000010 que corresponde a la dirección = 0x4342 10 ELO311 Tarea 02 02/99 Finalmente la instrucción queda estructurada de la siguiente forma: ori $v0, $s0, 0x4342 2 .- Lazo en MIPS Escribir el código para salvar y restaurar, para ello es preciso analizar cuidadosamente el código antes y después del “jal”. Loop: add lw slt beq addi lw lw $t1,$t3,$a0 $a1,4($t1) $t2,$0,$a1 $t2,$0,Exit $a0,$a0,1 $a2,0($s1) $a3,8($sp) 1 jal Hace algo 2 add lw add addi addi slti beq Exit: $t4,$v0,$t4 $t5,0($v1) $t4,$t5,$t4 $t3,$t3,-4 $t0,$t0,-1 $t6,$t0,5 $t6,$0,Loop Es necesario salvar algunos registros antes de invocar la subrutina, para que ésta no escriba sobre ellos, y al retornar de la subrutina pueda restaurarlos. Los registros que necesitan ser salvados son los siguientes: $ t0 : es necesario salvarlo ya que guarda un resultado que será ocupado nuevamente al salir de la subrutina. $ t3 : es necesario salvarlo ya que pasa de antes de la subrutina hasta después de ella sin modificaciones. $ t4 : al igual que $t0 guarda un resultado y este será ocupado a la salida de la subrutina 11 ELO311 Tarea 02 02/99 No es necesario guardar los demás registros ya que por convenio las funciones trabajan (modifican) los registros temporales. 1. - Código necesario para salvar los registros: addi sw sw sw $sp,$sp,-8 $t0,0($sp) $t3,4($sp) $t4,8($sp) Con esto se da el espacio suficiente para guardar estos tres registros en el stack. 2. - Código necesario para restaurar los registros y el stack: lw lw lw addi $t0,0($sp) $t3,4($sp) $t4,8($sp) $sp,$sp,8 Con esto se restauran los registros y se devuelve el espacio de memoria pedido al stack. 3. Ensamblar a mano, el siguiente código. Asumir el inicio de la zona de texto en 0x00400000. Comprobar los valores de los campos mediante el simulador. (El nombre main permite al simulador, con trap-handler, llamar al programa main.) texto main: Loop: End: sub addi lui ori andi slt bne sll j add jr paso $t0, $0, $0 $t1, $t0, 1 $t6, 0xffff $t6, $t6, 0xffff $t5, $t6, 0x5ca3 $t4, $t5, $t1 $t4, $0, End $t1, $t1, 1 Loop $v0, $t1, $0 $ra #1 #2 #3 #4 #5 #6 #7 #8 #9 #10 #11 dirección 0x00400000 0x00400004 0x00400008 0x0040000C 0x00400010 0x00400014 0x00400018 0x0040001C 0x00400020 0x00400024 0x00400028 12 ELO311 Tarea 02 02/99 Para ensamblar a mano este código nos basamos en los diferentes formatos que pueden tener las instrucciones: Operaciones. R Op 6 Rs 5 Rt 5 Rd 5 Transferencias: I Op 6 Rs 5 Rt 5 Inmediato 16 Shamn 6 Funct 5 Saltos: J Op 6 Dirección 26 Asociando cada registro con su binario equivalente (p.ej. $t0 es el registro 8 = 1000), que en los jumps el campo de 26 bits se extiende a 32 (4 los saca del primer dígito hexadecimal del PC el cual es cero y los dos restantes también del PC, considerando que todas las direcciones son múltiplos de 4) y ayudados por el manual de programación MIPS, podemos representar el código de la siguiente manera: Paso & dirección formato código binario instrucción #1 main: sub $t0, $0, $0 R 000000 00000 00000 01000 00000 100010 0x00004022 #2 addi $t1, $t0, 1 I 001000 01000 01001 0000 0000 0000 0001 0x21900001 #3 lui $t6, 0xFFFF I 001111 00000 01110 1111 1111 1111 1111 0x3C0EFFFF #4 ori $t6, $t6, 0xFFFF I 001101 01110 01110 1111 1111 1111 1111 0x35CEFFFF #5 andi $t5, $t6, 0x5CA3 I 001100 01110 01110 1111 1111 1111 1111 0x31CD5CA3 #6 Loop: slt $t4, $t5, $t1 R 000000 01101 01001 01100 00000 101010 0x01A9602A #7 bne $t4, $0, End I 000101 01100 00000 0000 0000 0000 0010 0x15800002 #8 sll $t1, $t1, 1 RI 000000 00000 01001 01001 00001 000000 0x00094840 #9 j Loop J 000010 0000 0100 0000 0000 0000 0001 01 0x08100005 #10 End: add $v0, $t1, $s0 R 000000 01001 00000 00010 00000 100000 0x01201020 #11 jr $ra R 000000 11111 00000 00000 00000 000100 0x03E00008 13 ELO311 Tarea 02 02/99 Ejemplo de ensamblaje: Formato R: #6 Loop slt $t4, $t5, $t1 - El OP RS: fuente 1= $t5 = registro número 13 RT: fuente 2= $t1 = registro número 9 RD: destino = $t4 = registro número 12 Shamt Funct La instrucción queda entonces: En hexadecimal: 0x = 000000 = 01101 = 01001 = 01100 = 00000 =101010 000000 01101 01001 01100 00000 101010 0000 / 0001 / 1010 / 1001 / 0110 / 0000 / 0010 / 1010 0 1 A 9 6 0 2 A 14