lenguaje ensamblador.. nose como accedes a este arreglo

Dudas y comentarios sobre otros lenguajes de programación. Si algún lenguaje recibe suficientes preguntas le añadimos nueva categoría.
Responder
Mensaje
Autor
carlos C
Mensajes: 20
Registrado: 19/10/2008 5:36 pm
Ubicación: los teques , miranda venezuela

lenguaje ensamblador.. nose como accedes a este arreglo

#1 Mensaje por carlos C » 02/12/2008 7:24 pm

en este codigo de el lengueja ensamblador intel IA-32, yo quiero leer un arreglo.,.. bueno leer e imprimir los datos q esten en cierto rango pedido al usuario... si me pudieran ayudar por favor

memoria: pushl $espacio #imprime un espacio
call printf #imprime un espacio
addl $4, %esp #desapila el espacio q se #imprimio
pushl $mens13 #apila el mensaje q mostrar
call printf
addl $4, %esp
/* codigo de opcion*/
memo:
pushl $mens17
call printf
addl $4, %esp
pushl $m1
pushl $format
call scanf
addl $8, %esp
movl m1,%esi # mueve m1 al registro %esi para poder compararlo
cmpl $0,%esi # Opcion para validar q sea una entrada en memoria valida
jl errormemo
cmpl $256, %esi
jge errormemo
pushl $mens18
call printf
addl $4, %esp
pushl $m2
pushl $format
call scanf
addl $8, %esp
movl m2,%edi # mueve m1 al registro %esi para poder compararlo
cmpl $0,%edi # Opcion para validar q sea una entrada en memoria valida
jl errormemo
cmpl $256, %edi
jge errormemo
/* movl %esi, %eax*/
cmpl %edi, %esi # esi tengo la primera posicion, en edi tengo la segunda posicion
jg errormemo


imprimir:
cmpl %edi, %esi # compara la primera posicion con la segunda posicion
je salida1 # cuando i=n salta a fin
pushl memoria1(,%esi,4)
pushl $format
call printf
addl $8, %esp
/*imprimir movl $0, memoria1(,%esi,4) */
incl %esi # incrementa %esi (i)
jmp imprimir # sigue recorriendo el arreglo


salida1:
pushl $mens9
call printf
addl $4, %esp
pushl $x
pushl $format1
call scanf
addl $8, %esp
jmp inicio

errormemo:
pushl $mens19
call printf
addl $4, %esp
jmp memo
desensamblar: pushl $espacio
call printf
addl $4, %esp
pushl $mens14
call printf
addl $4, %esp
/* codigo de opcion*/
pushl $mens9
call printf
addl $4, %esp
pushl $x
pushl $format1
call scanf
addl $8, %esp
jmp inicio

programa: pushl $espacio
call printf
addl $4, %esp
pushl $mens15
call printf
addl $4, %esp
/* codigo de opcion*/
pushl $mens9
call printf
addl $4, %esp
pushl $x
pushl $format1
call scanf
addl $8, %esp
jmp inicio

Avatar de Usuario
cheroky
Mensajes: 2571
Registrado: 22/09/2005 11:00 pm
Ubicación: Valladolid (España)

#2 Mensaje por cheroky » 03/12/2008 5:53 am

Analizar un listado en ensamblador no es tarea fácil, podrías al menos decir donde crees que falla.

De todos modos mirando por encima usas mal los punteros %esi y %edi, por ejemplo comparas la dirección almacenada en %esi con una dirección tal que $256 y esta es desconocida salvo que se use un offset.
Tampoco se aprecia si activas el flag de bifurcación cld, tambien mencionar que no tiene mucho sentido incrementar alguno de estos registros como operandos, pierden su función principal, para eso están los opcodes apropiados (lease movsl y familia).

Una forma conveniente de leer un array mediante esi y edi usando algunas instrucciones extendidas del ia32 para dichos punteros.

Código: Seleccionar todo

FT: .ascii "[%d]  \0"
cld               
movl $10,     %ecx  
movl $_src,  %esi    
lp:                
lodsl              
pushal
subl $8,     %esp  
movl %eax, 4(%esp) 
movl $FT,  (%esp) 
call _printf       
add $8,      %esp  
popal 
loop lp 

_src es el offset a un array de 40 bytes (10 elementos de int)
Si tienes alguna duda sobre algún opcode consulta los muchos manuales en linea que hay.

S2.
Imagen

carlos C
Mensajes: 20
Registrado: 19/10/2008 5:36 pm
Ubicación: los teques , miranda venezuela

gracias mi pana

#3 Mensaje por carlos C » 04/12/2008 7:04 pm

me quedaron algunas dudas... como para que con el CLD que le pone en cero el bit correspondiente a la bandera de dirección. es usado.. no entendi esa isntrucion..y mi pana lo q queia hacer era.. que dado un arreglo ..de o a 255 pos.. leer un rango osea 2 enteros e imprimir el contenido de ese rango del arreglo.....

yo lo hize asi? corre.. pero no se si le falta algo? imprimir: #imprime las posiciones de memoria que el usuario quiere ver
cmpl %edi, %esi # compara la primera posicion con la segunda posicion
jg salida1 # cuando i=n salta a fin
pushl %esi
pushl $mens20
call printf
addl $8, %esp
pushl memoria1(,%esi,4)
pushl $format
call printf
addl $8, %esp
pushl $espacio
call printf
addl $4, %esp
incl %esi # incrementa %esi (es decir incrementa el indice i)
jmp imprimir # sigue recorriendo el arreglo

Avatar de Usuario
cheroky
Mensajes: 2571
Registrado: 22/09/2005 11:00 pm
Ubicación: Valladolid (España)

#4 Mensaje por cheroky » 04/12/2008 9:10 pm

carlos C escribió:
me quedaron algunas dudas... como para que con el CLD que le pone en cero el bit correspondiente a la bandera de dirección. es usado.. no entendi esa isntrucion


cld lo pone a 0, en este estado los registros puntero %esi y %edi son incrementados cuando se usa el juego de instrucciones asociado, por ejemplo movsl incrementara en una unidad los registros aludidos. Por contra std activa el bit a 1 y aquí los registros punteros son decrementados en una unidad, por esa razón algunas literaturas lo denominan "bit de bifurcación".
Es importante dominar tales registros junto con (no todas) la instrucciones adecuadas para leer, mover y copiar bloques contiguos de memoria, ya que estas están optimizadas.

En cuanto al código, si la intención es imprimir las direcciones parece correcto aunque como ya te comente (ahora ya sabes mejor la razón) incrementar %edi con la instrucción incl es desperdiciar optimización, que es en ultima instancia lo que se pretende al codear en ensamblador.


S2.
Imagen

carlos C
Mensajes: 20
Registrado: 19/10/2008 5:36 pm
Ubicación: los teques , miranda venezuela

gracias mi pana2

#5 Mensaje por carlos C » 04/12/2008 9:20 pm

ok fino, mas claro!!!... esa instruccion q estaria como de mas.. el movl.. o todos los movl a aparezcan en el codigo afectan mucho a tiempo de ejecucion o al peso del programa?.. por ultimo, por mas q busco manuales no encuentro la sintaxis de esa instruccion... me explico. la de incrementar ls regisrtos esi y edi sin usar el movl... :? ... si peuedes ponerme un ejemplo o de darme una direccionde un manual donde salga.. gracias mi pana.... :wink:

Avatar de Usuario
cheroky
Mensajes: 2571
Registrado: 22/09/2005 11:00 pm
Ubicación: Valladolid (España)

#6 Mensaje por cheroky » 05/12/2008 1:56 am

No, no confundas movl con movsl el primero es para mover datos entre registros o de registro a memoria, el segundo no es un operador, es una instruccion. Por ejemplo, para copiar datos de un segmento a otro en zona global de datos .

Código: Seleccionar todo

 
cld                 #bit de direccion a 0                 
movl  $_src, %esi   #offset de _src a edi       
movl  $_dst, %edi   #no comment       
movl  $10, %ecx     #ecx esta asociado a movsl, n-reps      
rep movsb           #movemos bloques de 8 bits movs[b] de byte 

Ojo!, quizás haya que salvar previamente %edi y %esi al stack para luego recuperlas, depende de si son rutinas con frame stack independiente (funciones)
Para mas información busca manuales de GAS (Gnu Assembler)

Conociendo esto podemos implementar funciones muy optimizadas para gcc inline x86 assembler. He desarrollado estas de ejemplo sin usar clobbers tratando directamente la pila.

Funcion copia.

Código: Seleccionar todo

__cdecl void fastcpy(void *src, void *dst, size_t size)
{
__asm__ __volatile__
(

"pushl %edi                \n"
"pushl %esi                \n"
"cld                       \n"
"movl  8(%ebp),   %esi     \n"
"movl  12(%ebp),  %edi     \n"
"movl  16(%ebp),  %ecx     \n"
"rep movsb                 \n"
"popl %edi                 \n"
"popl %esi                 \n"
);

}
Esta para imprimir un array en bloques de 32 bits

Código: Seleccionar todo

__cdecl void print(void *e, size_t sz)
{

char * const fm = "%d ";

__asm__ __volatile__
(
"cld                  \n"
"movl  12(%ebp), %ecx \n"
"movl  8(%ebp),  %esi \n"
"movl -4(%ebp),  %ebx \n"
"lp:                  \n"
"lodsl                \n"
"pusha                \n"
"subl $8,    %esp     \n"
"movl %eax, 4(%esp)   \n"
"movl %ebx,  (%esp)   \n"
"call _printf         \n"
"add $8,     %esp     \n"
"popa                 \n"
"loop lp              \n"
);

}
Conclusión, los registros puntero son fundamentales para aprovechar ciclos de reloj.


S2.
Imagen

carlos C
Mensajes: 20
Registrado: 19/10/2008 5:36 pm
Ubicación: los teques , miranda venezuela

gracias mi pana

#7 Mensaje por carlos C » 06/12/2008 9:34 pm

muchas gracial amigo.. muy util tu respuesta y tu ayuda....

carlos C
Mensajes: 20
Registrado: 19/10/2008 5:36 pm
Ubicación: los teques , miranda venezuela

por favor

#8 Mensaje por carlos C » 09/12/2008 8:42 pm

mi pana por mas q trato no logro llenar un arreglo por teclado.. no me sale programa.... lo trato de hacer asi.. por favor ayudame a llenarlo,, osea guardar los datos q pido por teclado en el arreglo... es ensamblador ia 86


main:
leal arr, %ebx # %ebx=dir inicial del arreglo
movl $0, %ecx # %ecx=0 indice

movl $1, %eax # valor a guardar en el arreglo
genera: cmpl $9, %ecx # compara el indice con 9
jg fin # salta a fin cuando indice=10
movl %eax, (%ebx, %ecx, 4) # escribe valor en arr
incl %eax # incrementa el valor
incl %ecx # incrementa el indice
jmp genera

fin:
pushl %ecx
pushl $format
call printf
addl $8, %esp
movl $1, %eax # fin del programa
movl $0, %ebx
int $0x80

Responder

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 1 invitado