Foro de elhacker.net

Programación => ASM => Mensaje iniciado por: xoker en 3 Enero 2014, 20:35 pm



Título: Como imprimir los valores de un vector de enteros?
Publicado por: xoker en 3 Enero 2014, 20:35 pm
Buenas a todos, resulta que como se podran pensar soy muy novato con esto de ensamblador x86 y aqui viene mi duda:

Estoy tratando de imprimir los valores que contiene un vector, les pongo aqui el codigo que tengo por el momento:

Código:
.Const

.Data

Vec1 DW 8, 9, 2, 4, 5, 6, 1, 2, 3, 4, 7, 8, 9, 5, 6, 2, 3, 1, 4, 7 ;Aqui esta el vector

.Code

start:

Mov Ecx, Addr Vec1 ;Se le pasa la direccion base para movernos por todo el vector
Mov Eax, 0 ;Contador del vector, se pone el contador a 0

Invoke printf, "El valor de la posicion %d es: %d", Eax,[Ecx] ;[b]Aqui es donde viene la gracia, quiero ver el valor de la posicion 0 del vector y me sale un numero diferente!![/b]
Invoke puts, "", "\N"                                           ;Salto de Linea
Exit:
Invoke system, "pause"
Xor Eax, Eax
Invoke ExitProcess, Eax
;Fin del programa principal

Bueno pues como pongo en el codigo, lo que me ocurre es que en vez de aparecerme la primera posicion del vector lo que me aparece es un numero que no tiene nada que ver y que tampoco es la direccion de memoria del vector.

Creo que la teoria me la conozco y es lo que trato de aplicar, le paso a un registro la direccion donde se encuentra la direccion base del vector, y a partir de ahi voy recorriendo este aumentando la direccion en funcion de lo que ocupen los enteros, en este caso son dw por lo que se incrementara de 2 en 2 bytes, pero en la primera posicion el incremento es cero por lo que con mi codigo tendria que verse... He probado sumandole 2 o mas... quitandole los corchetes a Ecx y mil perradas, pero no lo cosigo  :rolleyes:.

Se que con este codigo no se puede recorrer todo el vector, he puesto aqui solo parte para que se vea la primea posicion para simplificarlo, mi problema solo es ese, con el bucle no tengo problemas (aun... xD)

A ver si me pueden decir donde esta mal el codigo!!

Un saludo!!


Título: Re: Como imprimir los valores de un vector de enteros?
Publicado por: _Enko en 4 Enero 2014, 15:22 pm
Hola, ten cuidado al usar ECX que  la funcion printf por ahi no preserva ecx. Recuerda que los contadores seguros  son esi, edi y ebx.

Te doy una pista si quieres imprimir numeros menores a 10.
8 no es lo mismo que "8"
El primero es un entero. El segundo es un caracter ascii.
El valor del caracter ascii "8" es  56. De "0" 48, "1" es 49...

http://www.asciitable.com/


Luego otro problema.
Vect1 DW....
mov ecx, addr vect1
printf..... [ecx]

printf como parametro te pide un Double Word.
DW creo que significa Data Word.
Necesitas un DD, Data Double Word.
De lo contrario en vez te tomar 8.... te va tomar 98 (primer y segundo elemento del vector invirtiendolos)

Saludos




Título: Re: Como imprimir los valores de un vector de enteros?
Publicado por: xoker en 4 Enero 2014, 15:33 pm
Hola, ten cuidado al usar ECX que  la funcion printf por ahi no preserva ecx. Recuerda que los contadores seguros  son esi, edi y ebx.

Te doy una pista si quieres imprimir numeros menores a 10.
8 no es lo mismo que "8"
El primero es un entero. El segundo es un caracter ascii.
El valor del caracter ascii "8" es  56. De "0" 48, "1" es 49...

http://www.asciitable.com/


Luego otro problema.
Vect1 DW....
mov ecx, addr vect1
printf..... [ecx]

printf como parametro te pide un Double Word.
DW creo que significa Data Word.
Necesitas un DD, Data Double Word.
De lo contrario en vez te tomar 8.... te va tomar 98 (primer y segundo elemento del vector invirtiendolos)

Saludos




Gracias por contestar, el tema de los caracteres ASCII no tengo problemas, al menos en C.

Ya he conseguido acceder a la primera posicion, el error era usar el registro Ecx tal como comentaste! He usado Esi y puesto DD en vez de DW (este fue el tipico cambio desesperado...) y a la primera me ha salido el 8. ¿Podrias explicarme un poco mas eso del registro Esi y Ecx? Comprendo que Ecx es un registro que tiene un proposito especifico, pero ¿sabes cual es el problema con printf que se modifica? Elegi el registro Ecx por ya tenia usados Eax y Ebx, vamos por orden, vaya ojo el mio que me fui a fijar en el que se modifica con printf... Ya no se me olvida en la vida!!! :(


Título: Re: Como imprimir los valores de un vector de enteros?
Publicado por: MCKSys Argentina en 4 Enero 2014, 15:47 pm
¿Podrias explicarme un poco mas eso del registro Esi y Ecx? Comprendo que Ecx es un registro que tiene un proposito especifico, pero ¿sabes cual es el problema con printf que se modifica?

Fijate esto: http://en.wikipedia.org/wiki/X86_calling_conventions (http://en.wikipedia.org/wiki/X86_calling_conventions)

Saludos!


Título: Re: Como imprimir los valores de un vector de enteros?
Publicado por: _Enko en 4 Enero 2014, 16:15 pm
Mh... fijate el link que te paso McksYS  para el tema de convenciones que es importante ^^

Luego, ecx es un registro de proposito general.
El llamado "Count Register" CX tenía un proposito específico en DOS 16 bit. En 32bit es un registro mas del monton.


Título: Re: Como imprimir los valores de un vector de enteros?
Publicado por: xoker en 7 Enero 2014, 10:36 am
Buenas, termine el programa que trataba de hacer, lo voy a poner aqui por si alguna persona le quiere echar un vistazo o a modo docente por si alguien quiere aprender, tengo mas o menos comentado para que sirve cada linea.

El programa es muy basico y lo que hace es ordenar un vector en orden creciente mediante el algoritmo de la burbuja. Lo ideal seria utilizar funciones en el codigo, pero no se hacerlas aun correctamente, ya que siempre me petan en el ret, se ve que no se guardar bien la direccion a la que debe volver...

Código:
;Ordenar un vector dado mediante el algoritmo de la burbuja

.Const

.Data

Vec1 DD 8, 10, 2, 4, 5, 6, 1, 2, 3, 4, 7, 8, 9, 5, 6, 2, 3, 1, 4, 7 ;Aqui esta el vector
Num DD 20 ;Numero de elementos

.Code

start:
Invoke printf, "Vamos a Ordenar el vector Vec1 ya iniciado mediante el algoritmo de la burbuja: "
Invoke puts, "", "\N"               ;Salto de Linea
Invoke printf, "Vector a Ordenar: "
Invoke puts, "", "\N"               ;Salto de Linea

;Imprimir por pantalla el vector:

imprimir:
Mov Ebx, 0 ;Ponemos el contador del bucle a cero.
Mov Esi, Addr Vec1 ;Se le pasa la direccion base para movernos por todo el vector
bucle:
Cmp Ebx, [Num] ;Comparacion de Eax y N
Je > fin ;Salta si Eax y N son iguales, por lo que seria igual a if(Eax < N)
Invoke printf, "%d, ", [Esi] ;Imprime el valor que hay en la direccion de memoria
Inc Ebx ;Eax++
Add Esi, 4 ;Se le suma 4 para movernos sobre el vector elemento a elemento
Jmp < bucle ;Salto incondicional, se usa < porque el salto es hacia atras.
fin:
Invoke puts, "", "\N"               ;Salto de Linea

;Fin parte imprimir Vector por pantalla

;Ordenar los elementos del vector con algoritmo burbuja
burbuja:
Mov Esi, 0 ;Contador i del bucle fuera
Mov Edi, 0 ;Contador j del bucle dentro
Mov Ebx, Addr Vec1 ;Metemos en Ebx la direccion base de vec1 para el bucle de fuera
while_fuera:
Cmp Esi, [Num]
Je > fin_whilefuera ;while(i < Num)
Mov Edi, Esi ;Hacemos j = i al iniciar el bucle
Mov Ebp, Ebx ;Metemos en Ebp la direccion base por donde vamos a empezar que sera en vec1[i]

while_dentro:
Cmp Edi, [Num]
Je > fin_whiledentro ;while(j < Num)
Mov Eax, [Ebx] ;No se pueden comparar [Ebx] y [Ebp] por lo que los hemos pasado a Eax y Ecx
Mov Ecx, [Ebp]
if:
Cmp Eax, Ecx
Jbe > fin_if ;if (Vec1[i] > Vec1[j])
;Invoke printf, "Valor de Vec1[%d]= %d <-- Vec1[%d]= %d, ", Esi, [Ebx], Edi, [Ebp]
;Invoke puts, "", "\N"               ;Salto de Linea
Mov Eax, [Ebx] ;aux1 = vec1[i]
Mov Edx, [Ebp] ;aux2 = vec1[j]
Mov [Ebx], Edx ;vec1[i] = aux2
Mov [Ebp], Eax ;vec1[j] = aux1
fin_if:
Inc Edi ;j++
Add Ebp, 4
Jmp while_dentro ;volvemos al bucle while dentro
fin_whiledentro:
Inc Esi ;i++ al terminar el while_dentro
Add Ebx, 4
Jmp while_fuera ;volveos al bucle while fuera
fin_whilefuera:

;Imprimimos de nuevo los resultados
Invoke printf, "Vector Ordenado: "
Invoke puts, "", "\N"               ;Salto de Linea

imprimir2:
Mov Ebx, 0 ;Ponemos el contador del bucle a cero.
Mov Esi, Addr Vec1 ;Se le pasa la direccion base para movernos por todo el vector
bucle2:
Cmp Ebx, [Num] ;Comparacion de Eax y N
Je > fin2 ;Salta si Eax y N son iguales, por lo que seria igual a if(Eax < N)
Invoke printf, "%d, ", [Esi] ;Imprime el valor que hay en la direccion de memoria
Inc Ebx ;Eax++
Add Esi, 4 ;Se le suma 4 para movernos sobre el vector elemento a elemento
Jmp < bucle2 ;Salto incondicional, se usa < porque el salto es hacia atras.
fin2:
Invoke puts, "", "\N"               ;Salto de Linea


;Fin parte Ordenar los elementos
Exit:
     
Invoke system, "pause"
Xor EAX, EAX
Invoke ExitProcess, EAX

;Fin del programa principal