[2021][Febrero][Problema 2]

[2021][Febrero][Problema 2]

de Sebastian Herrera Recondo -
Número de respuestas: 11

Buenas, estaba viendo la solución de este ejercicio y no entiendo la parte en donde se pushean los parámetros y la dirección de retorno al stack.

finwhile:                                                           largos proc 

 PUSH AX ; guardo dir ret                              POP AX ; dir ret 

 PUSH DI ; y largo actual                                POP SI ; SI=actual

 PUSH [SI+2] 

 CALL largos


Si se pushea  primero  la direccion de retorno, no quedaría "abajo" de los parámetros en el stack, y luego el primer pop  que se haría seria de [SI+2] y por lo tanto esto quedaria en AX?

En respuesta a Sebastian Herrera Recondo

Re: Ejercicio 2 examen febrero 2021

de Camilo Fossemale Zanotta -
Como la función devuelve el parámetro en el stack, después de hacer el CALL, si hacés POP vas a tener el parámetro que te puso en el stack la llamada. Luego sí vas a poder hacer POP a lo que hayas pusheado antes.
En respuesta a Camilo Fossemale Zanotta

Re: Ejercicio 2 examen febrero 2021

de Sebastian Herrera Recondo -
Entiendo, lo otro que no me cierra es el PUSH[SI+2], porque se le suma 2 para obtener la proxima palabra? Muchas gracias por la ayuda, me estas aclarando un monton de cosas
En respuesta a Sebastian Herrera Recondo

Re: Ejercicio 2 examen febrero 2021

de Camilo Fossemale Zanotta -
Los offset ocupan 2 bytes. El parámetro "actual" viene en el stack y es un offset respecto a DS que apunta a la base del nodo. Cada nodo está compuesto a su vez por dos offsets: string* y sig*.
Cuando pushea [SI+2] está poniendo en el stack el offset sig*, para hacer la llamada recursiva. Hace SI+2 porque cada offset ocupa 2 bytes. Te recomiendo mirar los videos prácticos de openfing, que tienen ejercicios parecidos.
En respuesta a Sebastian Herrera Recondo

Re: Ejercicio 2 examen febrero 2021

de Federico Rivero -
Ojo con esto! el 'dir ret' que se pushea primero efectivamente queda 'abajo' de los parámetros de stack. El que se retira al principio y que queda en AX es la dirección de retorno que coloca el CALL en el stack! Son dos direcciones de retorno diferentes, el PUSH AX guarda la dirección de retorno del llamador de esa rutina, y la dirección de retorno insertada en el stack por el CALL es para retornar a la instrucción inmediatamente posterior al CALL.

Saludos,
Federico
En respuesta a Federico Rivero

Re: Ejercicio 2 examen febrero 2021

de Sebastian Herrera Recondo -

Si, lo que no entiendo es en el orden que quedan los parámetros en el stack.
Según veo, antes de hacer 'ret' la rutina hace push DI y luego PUSH AX.

O sea que luego del call, cuando retorna y quita la dirección del stack, al hacer POP SI esta metiendo lo que había en DI en SI? Lo hice a lapiz y papel y no entiendo porque se hace POP SI si lo ultimo que hay en el stack a esa altura es DI a mi entender.

Otra duda que tengo es, cuando trabajamos con estructuras como estas donde tenemos punteros a chars y a siguientes, podemos asumir que si [SI] tiene el contenido del primer char de un string, [SI+1] va a tener el segundo char y asi sucesivamente? Consulto por la parte del codigo donde se hace

MOV BX, [SI] ; BX = string

while: 

 CMP byte ptr [BX+DI], 0 

 JZ finwhile 

 INC DI 

 JMP while

En respuesta a Sebastian Herrera Recondo

Re: Ejercicio 2 examen febrero 2021

de Federico Rivero -
Estimado,

O sea que luego del call, cuando retorna y quita la dirección del stack, al hacer POP SI esta metiendo lo que había en DI en SI? Lo hice a lapiz y papel y no entiendo porque se hace POP SI si lo ultimo que hay en el stack a esa altura es DI a mi entender.

Esto es porque lo que se está pasando es el resultado de la función. El resultado estaba en DI al momento de pushearlo (por eso PUSH DI), pero cuando se recibe en la línea siguiente al CALL, no hay por qué obtenerlo en el mismo registro. POP SI toma lo que está en el tope del stack y lo coloca en SI, pero lo que está en el tope del stack es simplemente un valor, no está 'ligado' a algún registro. Distinto es el caso de los PUSH y POP para guardar el contexto, en ese caso, al hacer PUSH AX, PUSH BX (ejemplo) para preservar los valores de los registros AX y BX, eventualmente se realiza POP BX, POP AX, en ese orden y con esos registros específicos, para recuperar en cada registro exactamente lo que tenían.

Otra duda que tengo es, cuando trabajamos con estructuras como estas donde tenemos punteros a chars y a siguientes, podemos asumir que si [SI] tiene el contenido del primer char de un string, [SI+1] va a tener el segundo char y asi sucesivamente? Consulto por la parte del codigo donde se hace

Sí, los arreglos se disponen en memoria de forma contigua y por lo tanto el "[SI + 1]" va a tener el siguiente carácter

Saludos,
Federico

En respuesta a Federico Rivero

Re: Ejercicio 2 examen febrero 2021

de Amalia Lucia Balestrazzi Silveira -
Buenas, hay algo en esta respuesta que me genera dudas.

Sí, los arreglos se disponen en memoria de forma contigua y por lo tanto el "[SI + 1]" va a tener el siguiente carácter

Pero [SI + 2] no tiene la direccion de actual->siguiente? SI fue declarado como 
POP SI ; SI=actual
Para obtener el tercer caracter del string (por ejemplo para compararlo con 0), no habria que hacer algo como 

MOV BX, [SI] ; BX = string
CMP [BX+2], 0

Haciendo directamente

CMP [SI+2], 0

No estamos viendo si la direccion del siguiente es null?

Como contexto dejo el struct

typedef struct{
char *string;
 nodo *siguiente;
}nodo;

Gracias

En respuesta a Amalia Lucia Balestrazzi Silveira

Re: Ejercicio 2 examen febrero 2021

de Federico Rivero -
Hola Amalia!

Con respecto a [SI + 1], el estudiante en su pregunta está asumiendo otra realidad donde [SI] apunta a un arreglo de caracteres, no se refiere al ejercicio del examen, donde sí, [SI] apunta a actual.

Lo demás que dijiste es todo correcto y creo que al confusión viene por lo que expliqué arriba. 

Puntualmente, es correcto lo que escribiste sobre que  [SI+2] en el contexto del ejercicio del examen apunta al siguiente nodo.

Saludos,
Federico