Disons que nous avons le code c ++ suivant:
int var1; __asm { mov var1, 2; }
Maintenant, ce que j’aimerais savoir, c’est que, si je ne voulais pas définir var1 en dehors de la directive __asm, que devrais-je faire pour la mettre à l’intérieur? Est-ce même possible?
Merci
Pour ce faire, vous devez créer une méthode “naked” avec _declspec (naked) et écrire vous-même le prolog et l’épilogue normalement créés par le compilateur.
Le but d’un prolog est de:
Un épilogue doit:
Voici un prolog standard
push ebp ; Save ebp mov ebp, esp ; Set stack frame pointer sub esp, localbytes ; Allocate space for locals push ; Save registers
et un épilogue standard:
pop ; Restore registers mov esp, ebp ; Restore stack pointer pop ebp ; Restore ebp ret ; Return from function
Vos variables locales commenceront alors à (ebp - 4)
et descendront à (ebp - 4 - localbytes)
. Les parameters de la fonction commencent à (ebp + 8)
et vont vers le haut.
Les variables locales sont allouées et libérées en manipulant l’espace disponible sur la stack d’appels via le registre ESP, à savoir:
__asm { add esp, 4 mov [esp], 2; ... sub esp, 4 }
En règle générale, cela est mieux géré en établissant une “trame de stack” pour la fonction appelante, puis en accédant aux variables locales (et aux parameters de la fonction) en utilisant des décalages dans la trame, au lieu d’utiliser directement le registre ESP, à savoir:
__asm { push ebp mov ebp, esp add esp, 4 ... mov [ebp-4], 2; ... mov esp, ebp pop ebp }
Il est impossible de créer une variable C dans l’assembleur: le compilateur C doit connaître la variable (c’est-à-dire son type et son adresse), ce qui signifie qu’elle doit être déclarée dans le code C.
Ce qui peut être fait est d’accéder aux symboles définis dans l’assembleur via des déclarations extern
en C. Cela ne fonctionnera pas pour les variables avec une durée de stockage automatique, car elles n’ont pas d’adresse fixe, mais sont référencées par rapport au pointeur de base.
Si vous ne souhaitez pas accéder aux variables en dehors du bloc asm
, vous pouvez utiliser la stack pour stocker les données locales de l’assembleur. N’oubliez pas que vous devez restaurer le pointeur de stack à sa valeur précédente lorsque vous quittez le bloc asm
, par exemple
sub esp, 12 ; space for 3 asm-local 32bit vars mov [esp-8], 42 ; set value of local var [...] push 0xdeadbeaf ; use stack [...] ; !!! 42 resides now in [esp-12] !!! add esp, 16 ; restore esp
Si vous ne voulez pas que les adresses relatives des variables locales changent chaque fois que vous manipulez la stack (utilisez push
ou pop
), vous devez établir un cadre de stack (enregistrer la base de la stack dans ebp
et les adresses locales relatives à cette valeur) comme décrit dans la réponse de cedrou .