Il faut savoir que sur le x86 , le FPU de base est mal branlé , pour ça que depuis qu'il y'a eu l'extension x64 , le FPU n'est plus utilisé et on utilise les instructions SIMD pour faire des calcul de float (avec addss , subss etc etc ). Pour ça que printf prend en argument xmm0 et non st0.
Bon perso je trouve une grosse partie du x86 mal foutu dans son ensemble
Oui je le déconseille , dejà qu'elle n'était pas top à l'époque (on faisait déjà mieux sur du MIPS ou du PowerPc) mais avec le temps c'est devenu des instructions complètement obsolètes Je pense qu'Intel ou AMD n'optimise même plus cette partie là , donc ils doivent eux aussi déconseillé d'utiliser ces instructions.
La fonction C printf n'a pas besoin de 8 octets de la pile pour fonctionner et l'explication est la suivante:
En 64 bits, la pile doit toujours être alignée sur une frontière de 16 octets or dans le premier cas tu enlèves 8 octets sur le pointeur de pile avec l'instruction sub rsp,8 et le call à la fonction printf (ou à n'importe quelle autres fonctions) enlève aussi 8 octets au pointeur de pile pour stocker l'adresse de retour. Donc soustraction de 16 octets : la pile est toujours alignée. Après printf, le dépilement de l'adresse de retour ajoute 8 octets à la pile et ton instruction add rsp,8 aussi soit 16 octets donc la pile est toujours alignée.
Dans le cas qui ne fonctionne pas, tu enlèves 8 octets puis tu les ajoutes ce qui revient à 0 de décalage mais le call printf enlève 8 octets dont la pile est décalée de 8 octets et le programme crashes !!
Tu pourras le vérifier sur d'autres appels de fonctions !! Et en plus si tu passes des paramètres par la pile, il faut tenir compte des push effectués.
Je suis passé a coté de cette info. Pour moi sachant que les adresses étaient sur 64bit l'alignement était sur 8 bytes et non 16 bytes.
genre si je fais
push al -> je suis pas aligné et je doit donc faire sub rsp 7
si je fait push rax -> je suis aligné rien a faire.
apparement c'est pas aussi simple
Je suppose donc que c'est pour ca que sur ghidra quand je décompile du c sur certain début de fonction il me fait un :
sub rsp, 0x8
call push l'adresse de retour, du coup il push 8 bytes et il faut réaligner la stack avec 8 bytes supplémentaire ? ce qui est bizarre c'est qu'il me le fait pas sur toute les fonctions. Peut être uniquement sur celle qui on besoin d'avoir leurs stack aligné. En tout cas merci pour ce rappel. Ca a l'air important.
Pour le push al, je ne pense pas qu'en 64 bits il soit possible de ne stocker qu'un octet.
Je pense que le compilateur la remplace par un push rax et qui utilise 8 octets.
Mais à vérifier !
push al stocke bien 1 octet C'est assez simple : les données 8 bits n'ont pas besoin d’être aligné les données 16 bits ont un alignement de 2 octets les données 32 bits ont un alignement de 4 octets les données 64 bits ont un alignement de 8 octets
Après que la pile a besoin d'un alignement de 16 octets , ça semble plus un besoin software que hardware.
Tu peux très bien push + appel de fonction sur autre chose qu'un alignement 16 octets, et ça marchera très bien
"Non, si la fonction est une fonction écrite en C dans une bibliothèque externe, cela ne fonctionnera pas !!"
Oui pour ça que j'ai dit que c'est une contrainte software et non hardware
Et c'était donc pour répondre à ceci : "Je suis passé a coté de cette info. Pour moi sachant que les adresses étaient sur 64bit l'alignement était sur 8 bytes et non 16 bytes." Et il a raison en 64 bits on a un alignement de 8 octets
Pour push al , ça ne marche pas c'est vrai autant pour moi , mais ça ne semble pas marcher aussi en non 64 bits ! Vu que l'instruction ne semble pas existé : https://www.felixcloutier.com/x86/push
Ce qui est logique de base le x86 est un proc 16 bits donc le minimum est de push 16 bits. (Mais le push 32 bits disparaît du coup en 64 bits )
si je dis que l'alignement est sur 8bytes en 64bits c'est que de ce que j'ai compris les bus mémoire et donné font 64bits et que le "but" de l'alignement est d'utiliser le moins de commande lecture/ecriture.
en effet pour les bit pas d'alignement. mais si on a 2bytes a lire et que c'est 2 byte commencent sur un offset de 7bytes alors il faudra 2 lectures.
Ce qui est dommage c'est qu'ils ne donnent pas la raison physique a cette norme. Si ils la donnent je ne l'ai pas vu. Sa me parait même faux leurs raisonnement a moins que des système x64 aient des bus mémoire de plus de 8bytes ? et a moins que j'ai mal compris, ca a l'air d'être leur explication :
The stack will always be maintained 16-byte aligned, except within the prolog (for example, after the return address is pushed), and except where indicated in Function Types for a certain class of frame functions.
malloc alignment
malloc is guaranteed to return memory that's suitably aligned for storing any object that has a fundamental alignment and that could fit in the amount of memory that's allocated. A fundamental alignment is an alignment that's less than or equal to the largest alignment that's supported by the implementation without an alignment specification. (In Visual C++, this is the alignment that's required for a double, or 8 bytes. In code that targets 64-bit platforms, it's 16 bytes.) For example, a four-byte allocation would be aligned on a boundary that supports any four-byte or smaller object.
- Edité par -Crixus- 9 juillet 2021 à 3:17:48
"Etre vrai, peu le peuvent." Friedrich Nietzsche
assembleur addition float
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
"Etre vrai, peu le peuvent."
Friedrich Nietzsche
"Etre vrai, peu le peuvent."
Friedrich Nietzsche
"Etre vrai, peu le peuvent."
Friedrich Nietzsche
"Etre vrai, peu le peuvent."
Friedrich Nietzsche
"Etre vrai, peu le peuvent."
Friedrich Nietzsche
"Etre vrai, peu le peuvent."
Friedrich Nietzsche