[2011][Diciembre][Problema 2]

[2011][Diciembre][Problema 2]

de Franco Pelua Camacho -
Número de respuestas: 4



Hola, buenas tardes. 

Para la parte (a) de este problema, llegué a la siguiente solución:

short M(short n) 

{

if(n > 100)

return n-10;

short recursive_parameter = M(n+11);

return M(recursive_parameter);

}


M proc:

pop BX ; BX = dir ret

pop AX ; AX = n

push BX ; Devuelvo la dirección de retorno al stack

cmp AX, 100

JA fin ; Si n > 100, saltamos a fin

add AX, 11 ; AX = n+11

push AX ;

call M ; M(n+11) guarda el resultado en el stack

call M ; M(M(n+11))

fin: 

sub AX, 10

push AX

ret

M endp

Luego vi la propuesta de solución y encontré algunas diferencias. Entre ellas, que en la solución se salvan los registros en el stack antes de comenzar la ejecución de la función, a pesar de que esto no es explicitamente solicitado en la letra. ¿Tengo que asumir que solo toman como válidas aquellas soluciones que salven los registros, a pesar de que esto último no este solicitado en la letra?

También, si encuentran errores en mi código, agradezco que los compartan por este medio, para poder rectificar. 
Gracias de antemano! saludos.

En respuesta a Franco Pelua Camacho

Re: [2011][Diciembre][Problema 2]

de Franco Pelua Camacho -
Analizando un poco más el código, vi que las dos últimas líneas son PUSH AX seguida de un RET.
¿Esto está mal verdad? En tanto el RET va a tomar del tope del stack el valor que AX almacenaba, y no al dirección de retorno que se supone debía tomar.

¿Podría ser el siguiente código una solución válida?

push AX
add SP, 2
ret
En respuesta a Franco Pelua Camacho

Re: [2011][Diciembre][Problema 2]

de Gonzalo Tejera -
Hola Franco.

El asunto de salvar registros tiene varias puntas. En algunas soluciones se indica como obligatorio salvar los registros modificados. Sin embargo, aúnen los casos que no se indique, es necesario salvar siempre los registros (contexto) requeridos para que la solución propuesta funcione correctamente.

Te falta un RET luego de la segunda llamada a M.

Como comentás en tu segundo mensaje, tu solución tiene un error importante respecto del manejo del stack.

Si bien lo que propones es una posible solución tiene algunos inconvenientes:
1. No es "prolijo" acceder al stack sobre el SP pues ese contenido puede verse afectado antes de ser leído (p.e. en caso de atenderse una interrupción).
2. Debes cambiar el código para que la segunda llamada acceda correctamente al parámetro de entrada.

Saludos, Gonzalo

En respuesta a Gonzalo Tejera

Re: [2011][Diciembre][Problema 2]

de Franco Pelua Camacho -

Gonzalo, muchas gracias por tu respuesta. 

Con tus consejos modifique el procedimiento, después chequee contra la solución propuesta y quedo similar. 

Una consulta respecto a este tipo de ejercicios. ¿Puede ser que una buena manera de visualizar la tarea de "limpiar el stack" sea imaginarte un escenario donde directamente la función va al paso base, y hacer la limpieza del stack acorde a la estructura que presenta en caso de que no se de un paso recursivo?

Por ejemplo, en mi solución, si suponemos un n > 100 de entrada (que va directo al paso base), el stack queda así:

n
dir retorno
BP
AX

Entonces, para limpiar el stack, basta con:

* Colocar el resultado en el lugar del parámetro
* POPear AX
* POPear BP

Esto funciona en el caso trivial de que la función no presente algún paso recursivo, pero me resulta más difícil verificarlo para el caso contrario, donde hay por lo menos uno o más pasos recursivos y el stack crece conforme a la cantidad de recursiones. 

En respuesta a Franco Pelua Camacho

Re: [2011][Diciembre][Problema 2]

de Gonzalo Tejera -
Sí, es razonable lo que propones.

Es importante verificar que el pasaje de parámetros (entrada y salida) en las llamadas recursivas implementa correctamente el pasaje de parámetros definido.

Saludos, Gonzalo