Je suis plutôt nouveau dans la programmation d'assemblage. J'utilise la plate-forme x86 avec GCC (Linux).Passage d'un pointeur sur une fonction d'assemblage
J'ai une fonction que je veux appeler à partir de C comme:
myfunc (unsigned char * s1, unsigned char * s2, int someint);
La fonction prendra les emplacements mémoire s1 et s2 et de les comparer, puis incrémenter et comparer, etc., effectuer des traitements comme ça va. C'est un peu comme memcmp mais je fais plus.
Ma question: si je passe un pointeur dans une fonction d'assemblage? Et puis comment je dis "donnez-moi la valeur stockée à cette adresse mémoire"?
Voici ce que j'ai jusqu'à présent:
Pour obtenir la première fonction arg (« s1 ») de la pile, je le fais (someaddress est un entier de 32 bits, et je travaille sur un 32 processeur -bit):
movl 8(%esp), %ecx
movl %ecx, someaddress
Si je mets somevar
dans %eax
(ou %ebx
, etc.), puis printf avec %p
, je vois que son adresse et l'adresse du pointeur unsigned char « s1
» je suis passé ce sont les mêmes. Mais je suspecte que ce que j'ai réellement fait est pris l'adresse de mémoire, l'a convertie en nombre entier, et puis mets cet entier dans une certaine partie.
Par exemple, si je puis le faire:
movl pos1, %eax
movl pos2, %ebx
cmp (%eax),(%ebx)
je reçois "Erreur: trop de références de mémoire pour` cmp '". Je ne suis pas tout à fait certain de ce que cela signifie, sauf « vous foiré » ;-)
Alors ...
- Comment passer un pointeur et le garder comme un pointeur? Comment utiliser la valeur dudit pointeur dans l'ensemble?
- (Par exemple, comme
*ptr
en C)
Est-ce que je veux regarder l'opérande LEA? J'utilise la "Professional Assembly Programming" de Richard Blum comme guide, mais Blum ne semble pas couvrir ce cas.
Mise à jour
Merci beaucoup pour votre réponse apprise!
Malheureusement, je ne suis toujours pas capable de déréférencer.
Voici un exemple simplifié. La fonction d'assemblage prend un pointeur et devrait lui faire écho.Au lieu de cela, je reçois:
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
Programme C:
#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;
}
programme de montage:
.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
Problèmes avec votre code mis à jour: Pour imprimer la valeur, vous poussez 32 bits alors que la variable est juste 8 bits. Vous pouvez l'étendre à 32 bits (ce que fait C) ou changer la chaîne de format. Notez que les 8 bits bas de -1543299247 évaluent en fait 81, comme prévu. Pour la deuxième impression et le retour: Vous essayez d'utiliser le double déréférencement en écrivant (str) et il n'y en a pas en x86. L'assembleur devrait lancer une erreur pour cela, si vous me le demandez, mais à la place il laisse tomber les parenthèses. – Jester