Soy bastante nuevo en la programación de ensamblaje. Estoy usando la plataforma x86 con GCC (Linux).Pasar un puntero a una función de ensamblaje
que tienen una función que quiero llamar desde C como:
myfunc (unsigned char * s1, unsigned char * s2, int someint);
La función se llevará a los lugares S1 y S2 de memoria y compararlos, incremente y comparar, etc., haciendo un poco de procesamiento como va. Esto es algo así como memcmp pero estoy haciendo más.
Mi pregunta: si paso un puntero a una función de ensamblaje? Y entonces, ¿cómo digo "dame el valor almacenado en esta dirección de memoria"?
Esto es lo que tengo hasta ahora:
Para obtener el primer argumento de función ("S1") de la pila, hago esto (someaddress es un número entero de 32 bits, y estoy trabajando en un 32 procesador de bits):
movl 8(%esp), %ecx
movl %ecx, someaddress
Si pongo somevar
en %eax
(o %ebx
, etc.) y luego printf con %p
, veo que su dirección y la dirección del puntero unsigned char "s1
" me pasaron son lo mismo Pero sospecho que lo que en realidad he hecho es tomar la dirección de la memoria, convertirla en un entero, y luego poner ese entero en alguna dirección.
Por ejemplo, si yo hago esto:
movl pos1, %eax
movl pos2, %ebx
cmp (%eax),(%ebx)
recibo "Error: demasiadas referencias a memoria para` cmp '". No estoy del todo seguro de lo que eso significa, excepto "te equivocaste" ;-)
Entonces ...
- cómo pasar un puntero y mantenerlo como un puntero?
- cómo usar el valor de dicho puntero en el ensamblaje? (Por ejemplo, como
*ptr
en C)
¿Deseo consultar el operando LEA?
Estoy utilizando la "Programación de montaje profesional" de Richard Blum como mi guía, pero Blum no parece cubrir este caso.
actualización
Muchas gracias por su respuesta aprendida!
Desafortunadamente, todavía no puedo quitar la referencia.
Aquí hay un ejemplo simplificado. La función de ensamblaje toma un puntero y debe repetirlo.En su lugar me sale:
first_ptr points to 81 (should be 81) <-- from C program
the value is -1543299247 <-- printf called from within assembler
the value is -6028513 <-- printf called from within assembler
my function returned -6028513 <-- return value printed from C program
Programa C: Programa
#include <stdio.h>
#include <string.h>
int main (void) {
unsigned char first;
unsigned char * first_ptr;
first = 'Q';
first_ptr = &first;
printf ("first_ptr points to %i (should be 81)\n",*first_ptr);
printf ("my function returned %i\n", myfunc(first_ptr));
return 0;
}
Asamblea:
.section .data
msg:
.asciz "the value is %i\n"
.section .bss
.lcomm str, 8
.section .text
.type myfunc, @function
.globl myfunc
myfunc:
# save stack
pushl %ebp
movl %esp, %ebp
# save string arg from stack to "str"
movl 8(%esp), %ecx
movl %ecx, str
# let's try printing the ecx dereference
pushl (%ecx)
pushl $msg
call printf
# put the value of str on the stack
# and call printf
pushl (str)
pushl $msg
call printf
# now return the character at pos1
movl (str), %eax
# restore the stack
movl %ebp, %esp
popl %ebp
ret
Problemas con su código actualizado: Para imprimir el valor, está empujando 32 bits mientras que la variable tiene solo 8 bits. Puede extenderlo a 32 bits (que es lo que hace C) o cambiar la cadena de formato. Tenga en cuenta que los 8 bits bajos de -1543299247 de hecho se evalúan a 81, como se esperaba. Para la segunda impresión y la devolución: Está intentando utilizar la doble desreferencia escribiendo (str) y no existe tal cosa en x86. El ensamblador debería arrojar un error para eso, si me preguntas, pero en lugar de eso cae silenciosamente entre paréntesis. – Jester