Programación General > ASM (Ensamblador)

[Artículo] Devolver Valores (ASM)

(1/2) > >>

-SB-:
Cuando tenemos un return en una funcion, la ejecucion no sigue, en el caso que has expuesto tu,
int mi_funcion()
{
//__asm mov eax,76
return 76;
}
una linea es similar a la otra porque no esta dentro de un ciclo por ejemplo, porque al hacer un return en un ciclo, la funcion termina, y si solo movemos al registro eax el valor, la funcion sigue corriendo..
void sin_valor()
{
return1(66);
return2(75);
return3(99);
}
Devolvemos tres valores, pero cuando termina la funcion si se devuelven dentro de un bucle?
Se te ocurre alguna solucion para esto?

Lo demas esta muy bien,

Un saludo!

Eternal Idol:
No se entiende muy bien lo que dijiste pero voy a tratar de responderte.
[code]
int devolucion()
{
   __asm
   {
     return1(50);
     return2(60);
     return3(70);
   }
   return;
}
[code]

Ese código es válido en VC++ y te permite devolver tres valores y terminar la función con el mismo return pero sin ningún valor evitando que cambie el valor de eax. Por lo tanto lo podes ubicar en un switch, dentro de un while, un for o donde quieras.

Por cierto, cuando la función llega a su última linea termina, no importa que no haya un return.

Saludos,
Mariano.

Eternal Idol:
¿Alguna vez se preguntaron que hace la instruccion return de CC++ y porque estamos limitados a devolver un solo valor cuando podemos pasarle varios a una funcion?

¿Que es lo que hace la instruccion return? Algo muy simple que es ajustar la pila segun la llamada, darle un valor a eax y saltar a la instruccion siguiente a la que llamo a nuestra funcion.


--- Código: ASM ---Lo que nos interesa es esto __asm { mov eax,valor }

En Windows el valor que devuelve una funcion se guarda en el registro eax; pero eax no es el unico registro que existe ni mucho menos, existen 4 registros de uso general (eax,ebx,ecx y edx).

eax viene de acumulador, ebx de base (no lo podemos usar para devolver nada porque Windows lo maneja), ecx de contador y edx de dato. Entonces tenemos 2 lugares mas donde devolver valores de una funcion, como si tuvieras un return1, return2 y un return3!!.

Vamos a ver un ejemplo muy simple para empezar:



--- Código: ASM ---#include <windows.h>void SayLong(int number){  char Data[5];  ltoa(number,Data,10);  MessageBox(0,Data,"El Numero",0);} int mi_funcion(){  //__asm mov eax,76  return 76;} void main(){  DWORD Resultado = 0;  Resultado = mi_funcion();  SayLong(Resultado);} 


Que hace este programa?
Algo muy simple muestra con un MessageBox el valor que devuelve la funcion mi_funcion, pero esto nos va a servir para demostrar lo que les conte antes; descomenten la linea que comienza con __asm (le dice al compilador que escriba una o varias instrucciones de ensamblador) y comenten la que empieza con return.

Que funciona exactamente igual? Si, si, Windows devuelve el valor de una funcion en eax.

Ahora vamos a lo bueno, si no existe solo eax y tambien tenemos 2 registros como ecx y edx eso significa que podemos devolver hasta 3 valores de una funcion!


--- Código: ASM ---#include <windows.h> void SayLong(int number){  char Data[5];  ltoa(number,Data,10);  MessageBox(0,Data,"El Numero",0);} void return1(DWORD Valor) { __asm mov eax,Valor }void return2(DWORD Valor) { __asm mov ecx,Valor }void return3(DWORD Valor) { __asm mov edx,Valor } void sin_valor(); void main(){  DWORD Valor1,Valor2,Valor3;  sin_valor();  __asm mov Valor1,eax  __asm mov Valor2,ecx  __asm mov Valor3,edx  SayLong(Valor1);  SayLong(Valor2);  SayLong(Valor3);} void sin_valor(){  return1(66);  return2(75);  return3(99);}

Finalmente ahora viene lo bueno, creamos un array de punteros (tipo string) en una funcion y la utilizamos en otra:


--- Código: ASM ---#include <windows.h> void SayLong(int number){  char Data[5];  ltoa(number,Data,10);  MessageBox(0,Data,"El Numero",0);} void return1(DWORD Valor) { __asm mov eax,Valor } DWORD Trozear(char *str){  DWORD Max = strlen(str);  DWORD Palabras = 0;  char **str_array = (char**)malloc(1*4); //un solo puntero a string  str_array[0] = (char*)malloc(1024);  ZeroMemory(str_array[0],1024);   for (int x = 0;x < Max;x++)  {    DWORD Pos = strlen(str_array[Palabras]);    if (str[x] == 32)    {      Palabras++;      str_array = (char**)realloc(str_array,(Palabras+1)*4);      str_array[Palabras] = (char*)malloc(1024);      ZeroMemory(str_array[Palabras],1024);    }    str_array[Palabras][Pos] = str[x];    str_array[Palabras][Pos+1] = 0;  }  __asm  {    mov ecx,[str_array]  }  return Palabras+1;} void main(){  DWORD Palabras = 0;  char *texto = (char*)malloc(1024);  strcpy(texto,"Esta es una prueba para que separe por espacios");  Trozear(texto);  char **str_ptr;  __asm mov Palabras,eax  __asm mov [str_ptr],ecx  SayLong(Palabras);  for (int y = 0;y < Palabras;y++)  {    MessageBox(0,str_ptr[y],"Palabra",0);    free(str_ptr[y]);  }  free(str_ptr);  free(texto);}  
Bueno, espero que les haya gustado, se que ya habra algunos diciendome que podria haber usado un doble puntero en el
prototipo de la funcion y obtener el mismo resultado; si, pero sin saber como funciona.
Por cierto en mi trabajo utilize este metodo para devolverme otros valores de una DLL creada por una compañera, asi seguia siendo compatible (en cuanto a parametros).

Saludos,
Mariano.

Autor: Mariano Ventaja

http://www.c0d3rz.com.ar

Descarga: http://www.c0d3rz.com.ar/foro/viewtopic.php?t=53

AnioN:
que ventaja tiene al uso de punteros?

Eternal Idol:
Ninguna, es un articulo informativo, no propone hacer esto en el desarrollo normal.

Navegación

[0] Índice de Mensajes

[#] Página Siguiente

Ir a la versión completa