Foro de elhacker.net

Programación => ASM => Mensaje iniciado por: class_OpenGL en 14 Diciembre 2015, 13:31 pm



Título: (Consulta) Intercambiador de variables en ensamblador (sintaxis de AT&T)
Publicado por: class_OpenGL en 14 Diciembre 2015, 13:31 pm
Hola, muy buenas. Estoy aprendiendo ensamblador y para ello lo estoy enlazando con las librerías estandar de C++. No sé mucho sobre la sintaxis de intel (estoy aprendiendo NASM), pero he conseguido el siguiente código (el cual está guardado en el archivo intercambiar.s)

Código
  1. .file "intercambiar.cpp"
  2. .text
  3. .globl __Z12intercambiarPiS_
  4. .def __Z12intercambiarPiS_; .scl 2; .type 32; .endef
  5. __Z12intercambiarPiS_:
  6. LFB0:
  7. .cfi_startproc
  8. pushl %ebp
  9. .cfi_def_cfa_offset 8
  10. .cfi_offset 5, -8
  11. movl %esp, %ebp
  12. .cfi_def_cfa_register 5
  13.  
  14. movl 8(%ebp), %eax
  15. movl 12(%ebp), %ebx
  16. movl %eax, 12(%ebp)
  17. movl %ebx, 8(%ebp)
  18.  
  19. popl %ebp
  20. .cfi_restore 5
  21. .cfi_def_cfa 4, 4
  22. ret
  23. .cfi_endproc
  24. LFE0:
  25. .ident "GCC: (GNU) 4.8.1"
  26.  

Lo que he hecho es conseguir el código base gracias al compilador g++ de MinGW y añadir el intercambiador de variables.

Lo que sería el intercambiador es el siguiente:

Código
  1. pushl %ebp
  2. movl %esp, %ebp
  3.  
  4. movl 8(%ebp), %eax
  5. movl 12(%ebp), %ebx
  6. movl %eax, 12(%ebp)
  7. movl %ebx, 8(%ebp)
  8.  
  9. popl %ebp
  10. ret

Lo que he hecho después es ejecutar el siguiente comando:
Código:
g++ -Wall -c intercambiador.s

Con el, he obtenido un fichero objeto

Ahora bien, cuando ejecuto el programa principal, no me intercambia las variables.

Aquí tenéis el programa principal en C++:

Código
  1. #include <iostream>
  2.  
  3. void intercambiar(int* lpnValorA, int* lpnValorB);
  4.  
  5. int main() {
  6. int nValorA, nValorB;
  7.  
  8. std::cout << "Introduzca el valor A: ";
  9. std::cin >> nValorA;
  10. std::cout << "Introduzca el valor B: ";
  11. std::cin >> nValorB;
  12.  
  13. intercambiar(&nValorA, &nValorB);
  14.  
  15. std::cout << "\nnValorA = " << nValorA << std::endl;
  16. std::cout << "nValorB = " << nValorB;
  17.  
  18. std::cin.get();
  19. std::cin.get();
  20. return 0;
  21. }

Pues eso, el intercambiador no hace nada

Soy novato en ASM, por lo que no seáis duros :D Gracias


Título: Re: (Consulta) Intercambiador de variables en ensamblador (sintaxis de intel)
Publicado por: fary en 14 Diciembre 2015, 19:28 pm
Eso es sintaxis AT&T.

¿Porqué no usar ASM Inline?

Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. int var1 = 1;
  5. int var2 = 2;
  6.  
  7. int main()
  8. {
  9.  
  10.    asm(".intel_syntax noprefix");
  11.    asm("mov eax, [_var1]");
  12.    asm("mov ecx, [_var2]");
  13.  
  14.    asm("mov [_var1] , ecx");
  15.    asm("mov [_var2], eax");
  16.    asm(".att_syntax noprefix");
  17.  
  18.    printf("Valor de var1: %i\n", var1);
  19.    printf("Valor de var2: %i\n", var2);
  20.  
  21.    return 0;
  22. }


Título: Re: (Consulta) Intercambiador de variables en ensamblador (sintaxis de intel)
Publicado por: class_OpenGL en 14 Diciembre 2015, 19:32 pm
¿Por qué usas el registro ecx? ¿Podrías usar el ebx? Por cierto, no usé inline porque quería acostumbrarme a los ficheros objeto y a enlazar. En cualquier caso, ¿no debería mi código funcionar?


Título: Re: (Consulta) Intercambiador de variables en ensamblador (sintaxis de intel)
Publicado por: fary en 14 Diciembre 2015, 20:16 pm
No entiendo esa sintaxis pero vamos quiero pensar que lo que tu estas haciendo es mover los datos a eax y no a la direccion a la que apunta  :xD

osea estas haciendo esto:

mov eax, 1
mov ebx, 2

En lugar de esto:

mov [eax],  1
mov [ebx] , 2

Prueba así:

Código
  1. pushl %ebp
  2.  
  3. movl %esp, %ebp
  4.  
  5. movl 8(%ebp), %eax
  6.  
  7. movl 12(%ebp), %ebx
  8.  
  9. movl %ecx, 12(%ebp)
  10.  
  11. movl (%eax), %ecx
  12.  
  13. movl %ecx, 8(%ebp)
  14.  
  15. movl (%ebx), %ecx
  16.  
  17.  
  18. popl %ebp
  19.  
  20. ret
  21.  

Repito, no se esa sintaxis, puede que hasta sea erronea.

Lo de usar ECX en lugar de EBX es por que me apetecia  :P

saludos.


Título: Re: (Consulta) Intercambiador de variables en ensamblador (sintaxis de intel)
Publicado por: class_OpenGL en 14 Diciembre 2015, 20:30 pm
Si, es que es alrevés xD

No entiendo por qué tiene que ser tan largo. En teoría, muevo las dos variables a los registros de propósito general y después les doy a las variables los valores intercambiados.

Muevo la primera a eax, muevo la seguda a ebx, le doy a la primera ebx y le doy a la segunda eax... No veo por qué no funciona en mi código. He conseguido que funcione con NASM con un código similar


Título: Re: (Consulta) Intercambiador de variables en ensamblador (sintaxis de AT&T)
Publicado por: fary en 14 Diciembre 2015, 20:33 pm
Has probado mi código arreglando mi error?  :rolleyes:



Título: Re: (Consulta) Intercambiador de variables en ensamblador (sintaxis de AT&T)
Publicado por: class_OpenGL en 14 Diciembre 2015, 21:05 pm
Es extraño. Tampoco funciona xD

Esta es la salida obtenida:

Código:
Introduzca el valor A: 10
Introduzca el valor B: 20

nValorA = 10
nValorB = 20


Título: Re: (Consulta) Intercambiador de variables en ensamblador (sintaxis de AT&T)
Publicado por: fary en 14 Diciembre 2015, 21:57 pm
Debuggea el código a ver en que falla.  :rolleyes:


Título: Re: (Consulta) Intercambiador de variables en ensamblador (sintaxis de AT&T)
Publicado por: class_OpenGL en 15 Diciembre 2015, 01:36 am
CREO QUE POR FIN SÉ LO QUE FALLA, pero el problema es que no sé como solucionarlo... xD

Bueno, el problema es que estoy intercambiando las DIRECCIONES de las variables. Es decir, lo que recibimos con el puntero ebp es la dirección de la dirección, y cuando añadimos corchetes (nasm), a lo que accedemos es a la dirección de la variable.

Código
  1. mov eax, [ebp+0x8] ; [ebp+0x8] es la dirección del primer parámetro
  2. mov ecx, [ebp+0xC] ; [ebp+0xC] es la dirección del segundo parámetro
  3.  
  4. mov [ebp+0xC], eax ; ¡Hemos intercambiado la dirección de ambas variables, no sus valores!
  5. mov [ebp+0x8], ecx

Lo que se me había ocurrido (aunque no ha funcionado), es añadir doble corchete (debería ser super intuitivo XD):

Código
  1. ...
  2. mov eax, [[ebp+0x8]] ;No funciona :(
  3. ...

El error que me lanza el ensamblador NASM es:
Código:
intercambiar.asm:13: error: expression syntax error
intercambiar.asm:14: error: expression syntax error
intercambiar.asm:15: error: expression syntax error
intercambiar.asm:16: error: expression syntax error

Si alguien sabe como acceder a los valores, por favor, compartidlo :D


Título: Re: (Consulta) Intercambiador de variables en ensamblador (sintaxis de AT&T)
Publicado por: xv0 en 15 Diciembre 2015, 23:07 pm
Normal te tira el error de sintaxis por el doble corchete. Si en ebp hay una direccion y la pasas a eax, y luego la copias sin mas, no estas copiando el valor.

Código
  1. movl 8(%ebp), %eax

Copio la direccion de ebp + 8, pero si es una direccion tienes que hacer esto de nuevo.

Código
  1. movl (%eax), %ebx

Y ya tienes el valor en ebx, y ya puedes pasarlo. Escribe una funcion en ASM con ASMinline y ahorrate todos esos problemas.

La funcion tiene dos variables, que esas son dos offsets, copia los valores de los offset a un registro de calculo general e intercambia.

Código
  1. ;intercambiar     variables eax y ebx
  2.  
  3. movl (%eax), %ecx
  4. movl (%ebx), %edx
  5.  
  6. movl %ecx, (%ebx)
  7. movl %edx, (%eax)

Cualquier cosa comenta.

Un saludo.


Título: Re: (Consulta) Intercambiador de variables en ensamblador (sintaxis de AT&T)
Publicado por: class_OpenGL en 16 Diciembre 2015, 00:51 am
He conseguido solucionar el problema!! La solución (en NASM) es esta:

Código
  1. segment .text
  2. global _change_values
  3.  
  4. _change_values:
  5. enter 0,0
  6. push ebx
  7.  
  8. mov edx, dword [ebp+8]
  9. mov ebx, dword [edx]     ; ebx = primer parámetro
  10. mov edx, dword [ebp+12]
  11. mov ecx, dword [edx]     ; ecx = segundo parámetro
  12.  
  13. ; mov dword [ebp+8], ecx   >> Intercambiador v1 NO FUNCIONA
  14. ; mov dword [ebp+12], ebx
  15.  
  16. mov edx, dword [ebp+8] ; Intercambiador v2
  17. mov [edx], ecx
  18. mov edx, dword [ebp+12]
  19. mov [edx], ebx
  20.  
  21. pop ebx
  22. leave
  23. ret
  24.  

Esto me plantea otra duda. ¿Por qué el intercambiador v1 no funciona? Sé que le intercambiador v2 si que debe funcionar perfectamente (de hecho, funciona :D), pero no entiendo porque en la primera versión que hice no puede funcionar...

Gracias por toda su ayuda!!

PD.: Sé que he puesto dword de sobra, pero aun quitándolos del intercambiador no funciona...



Aquí está la versión reducida (sinceramente, no sé si se puede optimizar más xD)

Código
  1. segment .text
  2. global _change_values
  3.  
  4. _change_values:
  5. enter 0,0
  6. push ebx
  7.  
  8. ; void intercambiar(int* valor_a, int* valor_b);
  9.  
  10. mov eax, dword [ebp+8]  ; eax = value_a
  11. mov ebx, dword [ebp+12] ; ebx = value_b
  12. mov ecx, [eax]          ; ecx = *value_a
  13. mov edx, [ebx]          ; edx = *value_b
  14. mov [eax], edx          ; *valor_a = edx >> *valor_a = *valor_b
  15. mov [ebx], ecx          ; *valor_b = ecx >> *valor_b = *valor_a
  16.  
  17. pop ebx
  18. leave
  19. ret
  20.  


Título: Re: (Consulta) Intercambiador de variables en ensamblador (sintaxis de AT&T)
Publicado por: fary en 16 Diciembre 2015, 07:36 am
Porque tu lo que le pasas a la función es un puntero.  :P


Título: Re: (Consulta) Intercambiador de variables en ensamblador (sintaxis de AT&T)
Publicado por: class_OpenGL en 18 Diciembre 2015, 21:22 pm
¡¡He caído dos veces en la misma trampa!! No me lo puedo creer... ¡QUE DURO ES APRENDER ASM! Pero es satisfactorio y útil :P


Título: Re: (Consulta) Intercambiador de variables en ensamblador (sintaxis de AT&T)
Publicado por: fary en 19 Diciembre 2015, 17:07 pm
Creo que no se puede resumir más...