Prof. Leopoldo Silva Bijit. 29-08

Transcripción

Prof. Leopoldo Silva Bijit. 29-08
UNIVERSIDAD TECNICA FEDERICO SANTA MARIA
DEPARTAMENTO DE ELECTRONICA
ELO312 Laboratorio de Estructuras de Computadores
Quiz 01 Laboratorio.
#include <stdio.h>
int n, d;
int f1(int r, int *d)
{ int dd=*d, q=0;
while (dd<=r) dd<<=1;
while (dd!=*d)
{ dd>>=1; q<<=1;
if (dd<=r) {r -=dd; q++;}
}
*d=q;
return(r);
}
int main(void)
{
n=26;d=4;
n = f1(n, &d);
printf(" r = %d q = %d \n", n, d );
return(0);
}
a)
b)
c)
d)
e)
Qué valor toma dd, después de realizado el primer while.
Qué valores toman r, dd y q después de realizado el segundo while.
Cual instrucción modifica a la variable d.
Qué realiza la función f1 sobre los parámetros de entrada.
En el assembler generado por lcc, dónde guarda las variables locales dd y q, y
con cuáles instrucciones las inicializa.
f) Cuál es el código que se genera para if (dd<=r) {r-=dd; q++;}
g) Explicar el código que se genera para
*d=q;
h) Qué guarda en el frame de f1.
i) Agregar el código y los datos necesarios para imprimir en la consola de SPIM,
según:
printf(" r = %d q = %d\n", n, d );
a), b), c) y d) un punto
e), f), g) y h) un punto
Un punto por lograr la especificación completa similar al printf del programa en C.
Solución.
a) Modificando el programa en C, del modo siguiente, pueden obtenerse las
respuestas a las preguntas a) y b). Conviene inicializar las variables estáticas(n y
d), ya que el compilador lcc, emplea la directiva .comm para asignar variables
no inicializadas y esa opción no está disponible en el simulador SPIM.
#include <stdio.h>
int n=0, d=0;
int f1(int r, int *d)
{ int dd=*d, q=0;
Prof. Leopoldo Silva Bijit.
29-08-2002
1
UNIVERSIDAD TECNICA FEDERICO SANTA MARIA
DEPARTAMENTO DE ELECTRONICA
ELO312 Laboratorio de Estructuras de Computadores
while (dd<=r) dd<<=1;
printf(" r = %d dd= %d\n",r, dd );
while (dd!=*d)
{ dd>>=1; q<<=1;
if (dd<=r) {r-=dd; q++;}
};
printf(" r = %d dd= %d q = %d\n",r, dd, q );
*d=q;
return(r);
}
int main(void)
{
n=26;d=4;
n = f1(n, &d);
printf(" r = %d q= %d\n",n, d );
return(0);
}
La ejecución del programa muestra:
r = 26 dd= 32
b) De manera similar
r = 2 dd= 4 q = 6
c) La variable d, es modificada por referencia, dentro de la función f1.
Mediante la expresión: *d=q;
d) La función f1 toma los parámetro valor de entrada r y el parámetro por
referencia d y forma:
r = n % d (el operador módulo en C es %)
q = n / d (es la división entera)
Además de retornar el resto r, como el valor de la función, retorna el cuociente en la
variable cuya dirección se pasó como segundo argumento.
Este es un ejemplo de una función que retorna dos valores.
e) La función f1 almacena las locales en los registros $23 y $30. La local q se
mantiene en $23, en $30 mantiene la local dd. En $a1 (el registro $5) viene la
dirección de la variable que se pasa como segundo argumento; es decir viene el
valor &d, la dirección de la variable estática d.
El siguiente código inicializa las locales:
#{ int dd=*d, q=0;
lw
$30, 0($5)
move
$23, $0
Prof. Leopoldo Silva Bijit.
29-08-2002
2
UNIVERSIDAD TECNICA FEDERICO SANTA MARIA
DEPARTAMENTO DE ELECTRONICA
ELO312 Laboratorio de Estructuras de Computadores
f) El primer argumento se pasa en $a0, es decir el valor de r se guarda en $a0.
Se emplea $30 para almacenar la local dd. Entonces se inicia el código del while,
saltando al rótulo L.3. Allí si r es menor o igual a dd se efectúa el bloque del while,
bifurcando al rótulo L.2. Que en este caso es simplemente el corrimiento a la
derecha, en una posición.
# while (dd<=r) dd<<=1;
b L.3
L.2: sll $30, $30, 1
L.3:
ble $30, $4, L.2
g) La función f1 almacena las locales en los registros $23 y $30. La local q se
mantiene en $23, en $30 mantiene la local dd. En $a1 (el registro $5) viene
la dirección de la variable que se pasa como segundo argumento. Dentro de
la función no se modifica el argumento a5; entonces, el código en C: *d=q;
puede simplemente traducirse en assembler por: sw $23, 0($5)
Lo cual modifica la variable, cuya dirección se pasó en $a5.
h) Las líneas que forman el frame son la siguientes:
f1:
.frame $sp, 8, $31
addu $sp, $sp, -8
.mask 0x40800000,-4
sw $23, 0($sp)
sw $30, 4($sp)
El frame, en el que se almacenan los registros s que empleará la rutina para almacenar
las locales es el siguiente:
sp
Salva $23
Salva $30
offset
Tope del frame
Fondo del frame
i) El código generado por lcc para invocar a printf en el programa principal es el
siguiente:
la $4, L.11
lw $5,n
lw $6,d
jal printf
Donde L.11 es el rótulo que contiene el string de control del printf. Que puede
anotarse.
Prof. Leopoldo Silva Bijit.
29-08-2002
3
UNIVERSIDAD TECNICA FEDERICO SANTA MARIA
DEPARTAMENTO DE ELECTRONICA
ELO312 Laboratorio de Estructuras de Computadores
L.11:
.asciiz " r = %d q= %d \n"
Lo relevante es que el decimal n se pasa como $a1 y d como $a2.
Entonces puede diseñarse el printf según:
#printf(" r = %d q= %d \n",n, d );
.globl printf
.text
.align 2
.ent printf
printf:
la $a0, m1
li $v0, 4 #imprime string que comienza en m1
syscall
move $a0, $a1 #imprime variable n
li $v0, 1 #imprime decimal en $a1
syscall
la $a0, m2
li $v0, 4 #imprime string que comienza en m2
syscall
move $a0, $a2 #imprime variable d
li $v0, 1 #imprime decimal en $a1
syscall
la $a0, m3
li $v0, 4 #imprime string con el \n que comienza en m3
j $31
.end printf
#printf(" r = %d q= %d \n",n, d );
.data
m1:.asciiz " r = "
m2:.asciiz " q= "
m3:.asciiz "\n"
Prof. Leopoldo Silva Bijit.
29-08-2002
4
UNIVERSIDAD TECNICA FEDERICO SANTA MARIA
DEPARTAMENTO DE ELECTRONICA
ELO312 Laboratorio de Estructuras de Computadores
f1:
.frame $sp,8,$31
addu $sp,$sp,-8
.mask 0x40800000,-4
sw $23, 0($sp)
sw $30, 4($sp)
#{ int dd=*d, q=0;
lw $30,($5)
move $23,$0
# while (dd<=r) dd<<=1;
b L.3
L.2: sll $30,$30,1
L.3:
ble $30,$4,L.2
b L.6
# { dd>>=1; q<<=1;
L.5:sra $30,$30,1
sll $23,$23,1
# if (dd<=r) {r-=dd; q++;}
bgt $30,$4,L.8
subu $4,$4,$30
la $23,1($23)
L.8:
# };
L.6:
# while (dd!=*d)
lw $24,($5)
bne $30,$24,L.5
# };
# *d=q;
sw $23,($5)
#return(r);
move $2,$4
L.1: lw $23,0($sp)
lw $30,4($sp)
addu $sp,$sp,8
j $31
.end f1
Prof. Leopoldo Silva Bijit.
29-08-2002
5

Documentos relacionados