elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.


 


Tema destacado: Java [Guía] Patrones de diseño - Parte 1


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación General
| | |-+  ASM (Moderador: Eternal Idol)
| | | |-+  Duda ensamblador, conversion de x86 a x64 (push y pop)
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Duda ensamblador, conversion de x86 a x64 (push y pop)  (Leído 1,331 veces)
Peaverin

Desconectado Desconectado

Mensajes: 3


Ver Perfil
Duda ensamblador, conversion de x86 a x64 (push y pop)
« en: 7 Febrero 2017, 03:34 »

Hola. Primero de todo decir que soy nuevo en este foro y tengo muchísimas cosas por leer y aprender, así que agradeceré a todos los que tengáis la paciencia necesaria para ayudarme.

Estoy empezando a aprender ensamblador, leyendo un libro que me recomendaron.

El libro se titulo Programming From the Ground Up, es un libro muy conocido.
Primero que todo decir que soy absolutamente nuevo en linux también, y practicamente en programación, así como totalmente nuevo en ensamblador.

El problema que tengo es que el libro lo explica todo para sistemas x86, cuyos registros tienen 32 bits de memoria, y mi ordenador tiene el procesador  x64 de 64bits, así como la gran mayoria de nuevos ordenadores, por lo que hay incompatibilidad entre los códigos que explican y los que yo puedo utilizar.

He estado leyendo por internet, y según dice, puedo utilizar normalmente las partes de 32 bits de los registros, ignorando los 32 restantes, escribiendo, por ejemplo, "%eax" en vez de "%rax". Hasta aquí todo bien, no he tenido ningún problema.
Pero el problema viene a la hora de guardar variables en el stack. Para ello no sirve utilizar, por ejemplo, "pushl %eax", sino que hay que utilizar "pushq %rax".

Dicho esto, necesito algo de ayuda. En el libro, se crea la función power (para elevar un numero a un exponente), y se utiliza esta. El ejemplo dado es para 32bits, por lo que se tendrían que hacer algunos cambios. Lo he  intentado, pero algo hago mal, puesto que el programa se linkea correctamente, pero cuando lo ejecuto, me dice "violación del segmento".  Aquí pongo el codigo original del libro y mi intento de "convertir" a 64 bits.

Código original 32 bits:
Código:
#PURPOSE:  Program to illustrate how functions work
#          This program will compute the value of
#          2^3 + 5^2
#
#Everything in the main program is stored in registers,
#so the data section doesn’t have anything.
.section .data
.section .text
.globl _start
_start:
pushl $3                  #push second argument
pushl $2                  #push first argument
call  power               #call the function
addl  $8, %esp            #move the stack pointer back
pushl %eax                #save the first answer before
#calling the next function
pushl $2                  #push second argument
pushl $5                  #push first argument
call  power               #call the function
addl  $8, %esp            #move the stack pointer back
popl  %ebx                #The second answer is already
#in %eax.  We saved the
#first answer onto the stack,
#so now we can just pop it
#out into %ebx
addl  %eax, %ebx          #add them together
#the result is in %ebx
movl  $1, %eax            #exit (%ebx is returned)
int   $0x80
#PURPOSE:  This function is used to compute
#          the value of a number raised to
#          a power.
#
#INPUT:    First argument - the base number
#          Second argument - the power to
#                            raise it to
#
#OUTPUT:   Will give the result as a return value
#
#NOTES:    The power must be 1 or greater
#
#VARIABLES:
#          %ebx - holds the base number
#          %ecx - holds the power
#
#          -4(%ebp) - holds the current result
#
#          %eax is used for temporary storage
#
.type power, @function
power:
pushl %ebp           #save old base pointer
movl  %esp, %ebp     #make stack pointer the base pointer
subl  $4, %esp       #get room for our local storage
movl  8(%ebp), %ebx  #put first argument in %eax
movl  12(%ebp), %ecx #put second argument in %ecx
movl  %ebx, -4(%ebp) #store current result
power_loop_start:
cmpl  $1, %ecx       #if the power is 1, we are done
je    end_power
movl  -4(%ebp), %eax #move the current result into %eax
imull %ebx, %eax     #multiply the current result by
#the base number
movl  %eax, -4(%ebp) #store the current result
decl  %ecx           #decrease the power
jmp   power_loop_start #run for the next power
end_power:
movl -4(%ebp), %eax  #return value goes in %eax
movl %ebp, %esp      #restore the stack pointer
popl %ebp            #restore the base pointer
ret

Mi intento en 64bits , que da el error "violación de segmento" (imagino que es porque intenta acceder a algún lugar de la memoria no reservado para el prgroama, desconozco el motivo) cuando, después de linquear, escribo "./power" en la consola de linux (hay algunos comentarios que he puesto tan solo para aclararme yo):
Código:
.section .data

.section .text

.globl _start
_start:
#ponemos en el stack al numero 3(será el segundo argumento) y al 2(primer #argumento)
pushq $3                  #push second argument
pushq $2                  #push first argument
call  power               #call the function
##Devolvemos el stack pointer a donde estaba antes (antes de los argumentos)
addl  $8, %esp            #move the stack pointer back
pushq %rax                #save the first answer before
#calling the next function
pushq $2                  #push second argument
pushq $5                  #push first argument
call  power               #call the function
addl  $8, %esp            #move the stack pointer back
popq  %rbx                #The second answer is already
#in %eax.  We saved the
#first answer onto the stack,
#so now we can just pop it
#out into %ebx
addl  %eax, %ebx          #add them together
#the result is in %ebx
movl  $1, %eax            #exit (%ebx is returned)
int   $0x80

#PURPOSE: This function is used to compute the value of a number raised to a power.

#INPUT
#First argument : the base number
#Second argument : the power to raise it to

#OUTPUT
# Will give the result as a return value

#THE POWER MUST BE 1 OR GREATER

# %ebx: base number
# %ecx: power

#Local variable: -4(%epb) current result
#%eax: temporary storage

.type power, @function
power:

##Pone el base pointer actual en el stack (el sack pointer %esp se cambia solo)
push %rbp
##Pone el valor del stack pointer en el base pointer
movl %esp, %ebp
##Le quita un word al stack pointer (para guardar una local variable)
subl $4, %esp

#8 es el first argument (porque es el segundo que metemos), 12 es el second (es el primero que metemos en el stack)
movl 8(%ebp), %ebx
movl 12(%ebp), %ecx
#Guardamos la base en la local storage
movl %ebx, -4(%ebp)

##Loop de hacer potencia:

potencia_loop:
##Si el exponente es 1, ya hemos acabado
cmpl $1, %ecx
je exit_loop

##Movemos el resultado actual a %eax
movl -4(%ebp), %eax
##Multiplicamos el resultado actual por la base 1 vez (se guarda en la derecha):
imull %ebx, %eax

##Guardamos el resultado actual en la local storage:
movl %eax, -4(%ebp)

##restamos 1 al exponente:
decl %ecx
jmp potencia_loop

exit_loop:
##mueve la local variable a %eax, que es el parametro de retorno
movl -4(%ebp), %eax
##restablece el stack pointer
movl %ebp, %esp
##pop quita el último valor del stack y lo pone en el registro indicado, es decir el antiguo %epb, y lo ponemos en %ebp (recuperamos el antiguo %ebp)
pop %rbp
##Retornamos a donde nos encontramos antes (adress guardada en el stack), y suma 4 al stack (se deshace de la return adress)
ret

Basicamente mi intento se basa en sustiuir todos los "pushl %exx" por "pushq rxx" y lo mismo con los pop... Obviamente no ha funcionado.

Agradecería que alguien que sepa del tema me pudiera ayudar y resolver esta duda, puesto que hasta que no consiga resolverlo no me quedo tranquilo y no puedo continuar con el libro.
Y cualquier recomendación de cualquier libro/recurso que me pueda ayudar a iniciarme en esto, también será muy agradecido. Gracias!


« Última modificación: 7 Febrero 2017, 16:49 por Peaverin » En línea

cpu2


Desconectado Desconectado

Mensajes: 925


Ver Perfil
Re: Duda ensamblador, conversion de x86 a x64 (push y pop)
« Respuesta #1 en: 7 Febrero 2017, 22:04 »

A la hora de trabajar con ebp, esp lo haces en 32 bits, si tu sistema esta corriendo en 64 bits, recuerda que las direcciones seran un quad, tienes que usar los de 64 bit, rsp, rbp.

Si estas en linux puedes hacer un strace, para saber donde esta la violacion, pero vamos que es por lo que te dije.

Un saludo.


En línea

Peaverin

Desconectado Desconectado

Mensajes: 3


Ver Perfil
Re: Duda ensamblador, conversion de x86 a x64 (push y pop)
« Respuesta #2 en: 8 Febrero 2017, 02:35 »

Gracias por la respuesta, pero eso mismo es lo que yo ya sabía y explico en el mensaje inicial, no obstante y aún haciendo los cambios de esp, ebp por rsp, rbp, me da el error de violación de segmento. Aquí pongo un codigo de lo que he intentado:
Código:
.section .data

.section .text

.globl _start
_start:
#ponemos en el stack al numero 3(será el segundo argumento) y al 2(primer #argumento)
pushq $3                  #push second argument
pushq $2                  #push first argument
call  power               #call the function
##Devolvemos el stack pointer a donde estaba antes (antes de los argumentos)
addl  $8, %esp            #move the stack pointer back
pushq %rax                #save the first answer before
#calling the next function
pushq $2                  #push second argument
pushq $5                  #push first argument
call  power               #call the function
addq  $8, %rsp            #move the stack pointer back
popq  %rbx                #The second answer is already
#in %eax.  We saved the
#first answer onto the stack,
#so now we can just pop it
#out into %ebx
addl  %eax, %ebx          #add them together
#the result is in %ebx
movl  $1, %eax            #exit (%ebx is returned)
int   $0x80

#PURPOSE: This function is used to compute the value of a number raised to a power.

#INPUT
#First argument : the base number
#Second argument : the power to raise it to

#OUTPUT
# Will give the result as a return value

#THE POWER MUST BE 1 OR GREATER

# %ebx: base number
# %ecx: power

#Local variable: -4(%epb) current result
#%eax: temporary storage

.type power, @function
power:

##Pone el base pointer actual en el stack (el sack pointer %esp se cambia solo)
push %rbp
##Pone el valor del stack pointer en el base pointer
movq %rsp, %rbp
##Le quita un word al stack pointer (para guardar una local variable)
subq $4, %rsp

#8 es el first argument (porque es el segundo que metemos), 12 es el second (es el primero que metemos en el stack)
movl 8(%rbp), %ebx
movl 12(%rbp), %ecx
#Guardamos la base en la local storage
movl %ebx, -4(%rbp)

##Loop de hacer potencia:

potencia_loop:
##Si el exponente es 1, ya hemos acabado
cmpl $1, %ecx
je exit_loop

##Movemos el resultado actual a %eax
movl -4(%rbp), %eax
##Multiplicamos el resultado actual por la base 1 vez (se guarda en la derecha):
imull %ebx, %eax

##Guardamos el resultado actual en la local storage:
movl %eax, -4(%rbp)

##restamos 1 al exponente:
decl %ecx
jmp potencia_loop

exit_loop:
##mueve la local variable a %eax, que es el parametro de retorno
movl -4(%rbp), %eax
##restablece el stack pointer
movq %rbp, %rsp
##pop quita el último valor del stack y lo pone en el registro indicado, es decir el antiguo %epb, y lo ponemos en %ebp (recuperamos el antiguo %ebp)
pop %rbp
##Retornamos a donde nos encontramos antes (adress guardada en el stack), y suma 4 al stack (se deshace de la return adress)
ret
En línea

cpu2


Desconectado Desconectado

Mensajes: 925


Ver Perfil
Re: Duda ensamblador, conversion de x86 a x64 (push y pop)
« Respuesta #3 en: 8 Febrero 2017, 21:41 »

Hay errores, estas sumando 8 a esp en la cuarta instruccion, ademas de otras sumas, si estas en 64 bits, tienes que usar syscall no int 0x80, se me olvido decirtelo. Los parametros no se suben al stack, si no se pasan a los registros.

http://stackoverflow.com/questions/2535989/what-are-the-calling-conventions-for-unix-linux-system-calls-on-x86-64

Mirate eso.

Un saludo.
En línea

Peaverin

Desconectado Desconectado

Mensajes: 3


Ver Perfil
Re: Duda ensamblador, conversion de x86 a x64 (push y pop)
« Respuesta #4 en: 9 Febrero 2017, 01:53 »

Hola, ya he conseguido compilar y ejecutar el programa sin ningún error.

Gracias por la ayuda.

Resuelto.
En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
duda con conversion de video
Multimedia
cacho* 1 934 Último mensaje 16 Noviembre 2007, 12:52
por Songoku
Duda sobre conversion DWORD
Programación C/C++
W0lFy 1 638 Último mensaje 2 Enero 2009, 11:14
por W0lFy
Duda Algoritmo Conversion « 1 2 »
Programación C/C++
Myth.ck 11 2,082 Último mensaje 21 Mayo 2009, 02:12
por Myth.ck
Duda-Delphi conversión de tipos
Programación General
h0oke 1 1,343 Último mensaje 26 Agosto 2009, 00:42
por h0oke
Duda de conversion en C
Programación C/C++
berni69 3 1,099 Último mensaje 27 Enero 2010, 22:22
por Eternal Idol
Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines