[Ensamblador 8086] Recursión y uso del stack

Iniciado por eltongabinghiman, 19 Diciembre 2011, 07:25 AM

0 Miembros y 1 Visitante están viendo este tema.

eltongabinghiman

Buenas gente.

Tengo bastantes dudas sobre el uso del stack en procedimientos recursivos, y sobre el diseño mismo de dichos procedimientos.

Me gustaría que alguien pueda aclararme la situación explicándome un poco o mediante alguna bibliografía que hable sobre eso específicamente, porque he googleado pero no encuentro mucha info.

Voy a citar un ejemplo de mi material de estudio para que quede claro, es el procedimiento recursivo asociado a el cálculo de la función factorial.


fact proc
   cmp ax,0  ; comparo n con cero
   je esCero
   dec ax    ; ajusto par·metro para la invocaciÛn
   call fact ; realizo la llamada recursiva
   inc ax
   mov cx,ax ; guardo ax pues mul lo modifica
   mul bx    ; calculo el paso recursivo
   mov bx,ax ; asigno el resultado del paso 
     ; recursivo
   mov ax,cx ; restauro ax
   jmp fin
esCero:
   mov bx,1  ; asigno el resultado del paso base
fin:
ret
fact endp



Algunas dudas:
   

  • Cuando se llama recursivamente al procedimiento, no es igual que un salto con jmp no? Qué se hace al llamar a un procedimiento?

  • Cuál es la función del stack al llamar a la recursión? Qué es lo que se almacena en el stack? (supongo que es la dirección de la instrucción siguiente a la línea que contiene la llamada recursiva, y que cuando se hace "ret" se estaría regresando a dicho lugar, pero no estoy seguro)
    Esto se procesa automáticamente mediante la Unidad de Control?


Les agradezco cualquier ayuda que puedan brindarme .

Saludos.





adastra

Respondiendo a tus preguntas:

1. JMP es distinto a la invocación de una función ya que el JMP realiza un salto en el flujo de ejecución hacia una dirección de memoria concreta, mientras que la invocación de un procedimiento tiene una dirección de "retorno" donde se almacena el resultado de procedimiento, volviendo al punto desde donde se ha ejecutado la función, es decir, no se "salta" a una dirección de memoria distinta (register EIP)

2. el uso de "mul" permite almacenar en "bx" el resultado de la función recursiva, por otro lado, en la stack se almacenan los parámetros del procedimiento y las variables locales que se inidican en el mismo, por ejemplo, los valores de los registers ax, cx y bx.

la ejecución de un programa es contralada por los registers de proposito general tales como (EAX, EBX, ECX y EDX) sin embargo, el register que mayor "peso" tiene es el EIP que es el que indica cual es la siguiente dirección de memoria que debe ser tratada por el procesador, el EIP es simplemente el puntero que indica cual es el flujo de ejecución del programa, por lo tanto es de vital importancia para entender correctamente Assembly.

Finalmente, si quieres entender todos estos conceptos puedes leer estas publicaciones:

Parte I
http://thehackerway.com/2011/04/10/assembly-en-gnulinux-para-hackers-parte-i/

Parte II
http://thehackerway.com/2011/04/12/assembly-en-gnulinux-para-hackers-newbies-parte-ii/

Parte III
http://thehackerway.com/2011/04/15/assembly-en-gnulinux-para-hackers-newbies-parte-iii/

Parte IV
http://thehackerway.com/2011/04/16/assembly-en-gnulinux-para-hackers-newbies-parte-iv/

Parte V
http://thehackerway.com/2011/04/17/assembly-en-gnulinux-para-hackers-newbies-parte%c2%a0v/

Parte VI
http://thehackerway.com/2011/04/18/assembly-en-gnulinux-para-hackers-newbies-parte-vi/

Parte VII
http://thehackerway.com/2011/04/20/assembly-en-gnulinux-para-hackers-newbies-parte-vii/

Parte VIII
http://thehackerway.com/2011/04/21/assembly-en-gnulinux-para-hackers-newbies-parte-viii/

Parte IX
http://thehackerway.com/2011/04/22/assembly-en-gnulinux-para-hackers-newbies-parte-ix-final/

eltongabinghiman

Te agradezco la ayuda!

Me queda una duda con respecto a lo que se guarda en el stack cuando se llama a la recursión.

Con respecto a lo siguiente:

Cita de: adastra en 19 Diciembre 2011, 09:49 AM
por otro lado, en la stack se almacenan los parámetros del procedimiento y las variables locales que se inidican en el mismo, por ejemplo, los valores de los registers ax, cx y bx.

Cuando decís que se guardan los registros ax, cx y bx, te referís a que se guardan automáticamente al hacer la llamada recursiva? Porque he visto ejemplos que eso se hace a mano (push) y no se me ocurre por qué debería hacerse en todos los casos.

Lo que sí pienso que se está guardando en el stack es el valor del registro IP, porque ret lo que hace es un salto al valor apuntado al tope de la pila, y pienso que ese tope, para que todo ande bien, debería ser el valor de IP al momento de llamar a la recursión. ¿Es correcto esto?

Ahora me surgió una duda con respecto al direccionamiento de memoria.
Siempre las palabras en memoria son del largo de los registros? O sea, para un procesador de 16 bits, los registros serán de largo 16 bits y la memoria estará dividida en bloques de 16 bits siempre?


adastra

en la Stack de forma automática se almacenarán las variables locales (inicializadas y sin inicializar) declaradas en el interior de la función y los parámetros de la misma, para todo lo demás tienes que usar "push" y "pop"