Quelles sont les différentes conventions d'appel en C/C++ et ce n'chaque dire?
Il existe différentes conventions d'appel disponible en C/C++: stdcall
, extern
, pascal
, etc. Combien de telles conventions d'appel sont disponibles, et ce que chacun veut dire? Existe-il des liens qui les décrire?
J'ai googlé pour les "conventions d'appel": - msdn.microsoft.com/en-us/library/984x0h58.aspx - msdn.microsoft.com/en-us/library/wda6h6df.aspx
Voir article de Wikipédia et aussi Raymond Chen série sur l'histoire des conventions d'appel: partie 1, partie 2, partie 3 (c'est surtout ce que vous demandez), partie 4 et 5.
Voir article de Wikipédia et aussi Raymond Chen série sur l'histoire des conventions d'appel: partie 1, partie 2, partie 3 (c'est surtout ce que vous demandez), partie 4 et 5.
OriginalL'auteur Ram | 2009-06-04
Vous devez vous connecter pour publier un commentaire.
Ni Standard C ni C++ Standard a un tel concept - ces sont des caractéristiques spécifiques des compilateurs, éditeurs de liens et/ou des systèmes d'exploitation, de sorte que vous devriez vraiment indiquer les technologies spécifiques qui vous intéressent.
Veuillez vérifier l'historique d'édition avant de faire des commentaires de ce genre.
Oh, c'est pour ça que je ne comprenais pas pourquoi syntaxe C++ soudain autorisés pour ce type supplémentaire d'être poussé dans entre le type de retour et le nom de la fonction? Ce n'est pas vraiment une partie de l'ordinaire de la syntaxe C++?
Bien que le K&R C a un
fortran
mot-clé réservé pour cette, qui ne compilateur jamais utilisé.OriginalL'auteur
Réponse Simple: - je utiliser cdecl, stdcall, et fastcall. J'utilise rarement fastcall. stdcall est utilisé pour appeler des fonctions de l'API Windows.
Réponse détaillée (Vol à partir de Wikipedia):
cdecl - En cdecl, sous-routine arguments sont passés sur la pile. Les valeurs entières et les adresses mémoire sont retournés dans le registre EAX, des valeurs à virgule flottante dans le ST0 registre x87. Les registres EAX, ECX et EDX sont de l'appelant-sauvé, et le reste sont callee-saved. Le x87 registres virgule flottante ST0 à ST7 doit être vide (sauté ou libéré) lors de l'appel d'une nouvelle fonction, et ST1 pour ST7 doit être vide lors de la sortie d'une fonction. ST0 doit également être vides lorsqu'il n'est pas utilisé pour le retour d'une valeur.
syscall - Ce qui est similaire à cdecl dans les arguments sont poussés à droite à gauche. EAX, ECX et EDX ne sont pas conservées. La taille de la liste de paramètres dans doublewords est passé à AL.
pascal - les paramètres sont poussés sur la pile de gauche à droite (en face de cdecl), et le destinataire de l'appel est responsable de l'équilibrage de la pile avant le retour.
stdcall - Le stdcall[4] convention d'appel est une variation sur la convention d'appel Pascal dans lequel le destinataire de l'appel est responsable du nettoyage de la pile, mais les paramètres sont poussés sur la pile de droite à gauche, comme dans le _cdecl convention. Les registres EAX, ECX et EDX sont désignés pour une utilisation à l'intérieur de la fonction. Les valeurs de retour sont stockées dans le registre EAX.
fastcall - __fastcall convention (aka __msfastcall) passe les deux premiers arguments (évaluée de gauche à droite) qui s'inscrivent dans ECX et EDX. Arguments restants sont poussés sur la pile de droite à gauche.
vectorcall - Dans Visual Studio 2013, Microsoft a introduit l' __vectorcall convention d'appel en réponse à des préoccupations quant à l'efficience de jeu, graphique, audio/vidéo, et les développeurs de codec.[7] Pour IA-32 et de code x64, __vectorcall est similaire à __fastcall et l'original x64 conventions d'appel, respectivement, mais les étend en charge la transmission de vecteur arguments à l'aide de SIMD registres. Pour x64, lorsque l'un quelconque des six premiers arguments sont les types de vecteurs (float, double, __m128, __m256, etc.), ils sont transmis via le correspondant XMM/YMM registres. De même pour IA-32, jusqu'à six XMM/YMM registres sont attribués séquentiellement par type de vecteur arguments de gauche à droite, peu importe la position. En outre, __vectorcall ajoute le support pour le passage de l'homogène vecteur d'agrégation (HVA) des valeurs, qui sont des types de composé composé uniquement de quatre identique types de vecteurs, en utilisant les mêmes six registres. Une fois que les registres ont été alloués pour le type de vecteur arguments, le solde non utilisé des registres sont alloués à HVA arguments de gauche à droite, peu importe la position. Vecteur résultant type et HVA valeurs sont renvoyées à l'aide de la première de quatre XMM/YMM registres.
safecall - n Delphi et Free Pascal sur Microsoft Windows, le safecall convention d'appel encapsule COM (Component Object Model) de la gestion d'erreur, donc les exceptions ne sont pas divulgués à l'appelant, mais sont signalés dans le HRESULT valeur de retour, comme l'exige COM/OLE. Lors de l'appel d'un safecall fonction de code Delphi, Delphi aussi vérifie automatiquement le HRESULT retourné et lève une exception si nécessaire.
La safecall convention d'appel est la même que la convention d'appel stdcall, sauf les exceptions sont transmis à l'appelant dans EAX comme un HResult (au lieu de FS:[0]), alors que le résultat de la fonction est passée par référence sur la pile comme si c'était une finale "paramètre". Lors de l'appel de Delphi fonction de Delphes, cette convention d'appel apparaîtra comme toute autre convention d'appel, parce que bien que des exceptions sont passés dans EAX, ils sont automatiquement convertis au bon exceptions par l'appelant. Lors de l'utilisation des objets COM créés dans d'autres langues, le HResults sera automatiquement majoré comme des exceptions, et le résultat pour Obtenir des fonctions est dans le résultat plutôt que d'un paramètre. Lors de la création d'objets COM en Delphi avec safecall, il n'y a pas besoin de s'inquiéter à propos de HResults, comme des exceptions peuvent être soulevées comme d'habitude, mais sera considéré comme HResults dans d'autres langues.
Microsoft X64 Convention d'Appel - Microsoft x64 convention d'appel[12][13] est suivie sur Windows et de pré-amorçage UEFI (pour les longues mode sur x86-64). Il utilise les registres RCX, RDX, R8, R9 pour les quatre premières entier ou un pointeur arguments (dans cet ordre), et XMM0, XMM1, XMM2, XMM3 sont utilisés pour virgule flottante arguments. D'autres arguments sont poussés sur la pile (de droite à gauche). Entier les valeurs de retour (similaire à x86) sont retournés dans RAX, si 64 bits ou moins. Virgule flottante valeurs de retour sont retournés dans XMM0. Les paramètres de moins de 64 bits ne sont pas zéro étendu; les bits ne sont pas remis à zéro.
Lors de la compilation pour l'architecture 64 bits dans un contexte Windows (que ce soit à l'aide de Microsoft ou non des outils de Microsoft), il y a une seule convention d'appel – celle décrite ici, de sorte que stdcall, thiscall, cdecl, fastcall, etc., sont désormais une seule et même chose.
Dans Microsoft x64 convention d'appel, c'est l'appelant responsabilité d'allouer 32 octets de "l'ombre" de l'espace" sur la pile juste avant l'appel de la fonction (quel que soit le nombre de paramètres utilisés), et à la pop de la pile après l'appel. L'ombre de l'espace est utilisé pour le déversement RCX, RDX, R8 et R9,[14], mais doit être disponible pour toutes les fonctions, même ceux avec moins de quatre paramètres.
Les registres RAX, RCX, RDX, R8, R9, R10, R11 sont considérées volatiles (de l'appelant-enregistré).[15]
Les registres RBX, RBP, RDI, le RSI, les RER, R12, R13, R14 et R15 sont considérés comme non volatile (callee-saved).[15]
Par exemple, une fonction prenant 5 arguments entiers va prendre la première à quatrième dans les registres, et le cinquième sera poussé sur le dessus de l'ombre de l'espace. Ainsi, lorsque la fonction appelée est entré, la pile sera composé de (par ordre croissant) l'adresse de retour, suivi par l'ombre de l'espace (32 octets), suivi par le cinquième paramètre.
En x86-64, Visual Studio 2008 stocke des nombres à virgule flottante dans XMM6 et XMM7 (ainsi que XMM8 par XMM15); par conséquent, pour x86-64, écrit par l'utilisateur de l'assemblée routines de langue doit préserver XMM6 et XMM7 (par rapport à x 86 où l'utilisateur écrit assemblée routines de langue n'a pas nécessité de préserver XMM6 et XMM7). En d'autres termes, écrit par l'utilisateur de l'assemblée routines de langue doit être mis à jour pour sauvegarder/restaurer les XMM6 et XMM7 avant/après de la fonction lors de l'être porté à partir de x86, x86-64.
OriginalL'auteur Russell Hankins
Standard C++ a essentiellement deux:
extern "C"
etextern "C++"
. Le second est la valeur par défaut, cet ancien utilisé lorsque vous avez besoin de lien en code C. Les compilateurs peuvent définir d'autres cordes à part "C" et "C++". Par exemple, un compilateur compatible avec son frère Pascal peut définirextern "Pascal".
Malheureusement, certains compilateurs ont inventé des mots-clés plutôt. Dans ces cas, consultez la documentation du compilateur.
Eh bien, comme vous l'avez mentionné, ISO C++ n'est pas avoir une notion de "conventions d'appel", et ne correspond pas exactement à décrire ce lien spécifications sont, soit uniquement ce que vous pouvez faire avec eux. C'est donc une zone grise en gros. C'est pourquoi j'ai donné
extern "Pascal"
comme un exemple. Un compilateur peut certainement utiliser un autre registre schéma d'allocation pour les fonctions avec ce lien spécification.Non, désolé, vous êtes l'introduction d'un MSVC centrée sur le point de vue ici. L'ISO n'a absolument PAS dire que le couplage spécification est (juste) de nommage. Et l'une des raisons qui qsort() est surchargée sur le couplage est parce que sur la non-MSVC plates-formes de la pile des arrangements ("les conventions d'appel") ne diffèrent entre extern "C" et extern "C++".
Je ne sais pas pourquoi cela a été downvoted - lien de la spécification est certainement la seule chose dans la norme C++ qui peuvent modifier les conventions d'appel.
extern "Pascal" et extern "C" sont à la fois le couplage des spécifications ET de la convention d'appel de spécification. Ou sinon, comment devrait savoir au compilateur que la fonction première est d'être appelé avec Pascal conventions d'appel? Pascal généralement pushs les arguments de la droite vers la gauche sur la pile, puis l'adresse de retour. Le destinataire de l'appel est la compensation de la pile sur le retour. C n'est généralement exactement le contraire (en raison de la longueur variable des listes d'arguments), en poussant de gauche à droite et que l'APPELANT efface la pile comme lui seul sait le nombre d'arguments qu'il avait fournis.
OriginalL'auteur MSalters
Cela concerne ce que l'ordre de mettre les paramètres sur la pile d'appel, et quand utiliser l'appel par valeur et/ou de l'appel par la référence à la sémantique. Ils sont spécifiques de compilateur extensions destinées à simplifier la programmation multilingue.
OriginalL'auteur dmckee
Ils sont spécifiques à la plateforme extensions nécessaires pour appeler des fonctions dans certaines bibliothèques, en particulier de l'API Win32. Ils sont non standard et spécifiques à chaque compilateur, bien que MSVC les options sont les de facto standard pour Windows x86. Normalement, une bibliothèque qui a besoin d'eux va les déclarer dans les fichiers d'en-tête et ils vont travailler de manière transparente. La principale différence entre eux est que C historiquement utilisé un moins efficace la convention qui a permis à un nombre variable d'arguments de n'importe quel type, tandis que Windows et la plupart des autres langues n'différemment. Beaucoup de différences, cependant, tels que pousser gaucher ou droitier et avoir l'appelant ou de l'appelé fonction de nettoyer, ont été assez arbitraire.
Ils sont sans grande importance à la version 64 bits de code: les guerres saintes sur les conventions d'appel ne s'est jamais passé sur ces plates-formes.
Il y a quelques cas où vous pourriez avoir besoin d'ajouter un de ces à une fonction. Un module C++ qui doit faire le lien avec les modules écrits dans d'autres langues (et parfois même d'autres compilateurs C++) auront à utiliser les
extern "C"
convention de nommage pour la compatibilité. Une fonction de rappel doit utiliser la même convention d'appel que l'appelant, qui, avec l'API Windows estCALLBACK
, pas la valeur par défaut. Une bibliothèque partagée pourriez avoir besoin pour exporter ses fonctions avec une autre convention d'appel qu'il utilise en interne, ou souhaitez peut-être son utilisation de__cdecl
explicite dans le cas où le défaut changements. Vous pourrait ou ne pourrait pas obtenir de meilleures performances de__fastcall
sur certaines plates-formes: surtout à des vitesses allant jusqu'court de la feuille des fonctions avec un ou deux paramètres, et pourrait faire de certains programmes plus lent.OriginalL'auteur Davislor
fastcall est optimisé, mais personne ne l'utilise
OriginalL'auteur Mandrake