Précédent   Forum des professionnels en informatique > Autres langages > Assembleur
Assembleur Forum d'entraide Assembleur. Avant de poster -> F.A.Q Assembleur Tutoriels Assembleur
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 12/06/2011, 14h30   #1
Invité régulier
 
Inscription : juin 2010
Messages : 4
Détails du profil
Informations forums :
Inscription : juin 2010
Messages : 4
Points : 7
Points : 7
Par défaut Blocs try catch et asm

Bonjour,

je me pose pas mal de question vis à vis des blocs try{} catch() {} du c++, une fonctionnalité que j'utilises énormément mais dont j'ai très peu de connaissances vis à vis du fonctionnement interne, voici mes questions :
- comment les try/catch, ainsi que les instructions throw sont-elles gérées au niveau assembleur ?
- quel code asm génère un compilo c++ comme gcc pour gérer cette fonctionnalité ?
- quelle est la différence en bas niveau entre une exception lancée par un throw du style :

Code :
1
2
3
 
if (dadou == 0)
   throw new Exception("Dadou is NULL !");
et une exception intrinsèque du CPU comme une division par zero ?

- est-ce qu'englober un bloc de code dans un try/catch va allourdir l'exécution ?
- existe-t-il des failles de sécurité concernant les blocs try/catch qui requièrent une certaine prudence lors du codage d'une appli ?

Si quelqu'un pouvait me rediriger vers un article simple, ou me filer une explication çà m'intéresse vraiment, j'ai la facheuse habitude de balancer des try/catch à la volée sans vraiment réfléchir.
artefactman est déconnecté   Envoyer un message privé Réponse avec citation 20
Vieux 12/06/2011, 17h04   #2
Membre Expert
 
Avatar de supersnail
 
Homme
Inscription : novembre 2006
Messages : 1 402
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations forums :
Inscription : novembre 2006
Messages : 1 402
Points : 1 991
Points : 1 991
Bonjour,

Les try/catch n'existent tout simplement pas en assembleur. Sous Windows, il existe un mécanisme de SEH handler, qui est expliqué ici: http://www.indahax.com/reverse/struc...eption-handler (à noter que les try/catch en C++ se servent de ce système ).
Cependant, je n'ai aucune idée concernant l'implémentation des exception handler sous Linux et UNIX en général...
__________________
Toute question technique envoyée en MP ira directement à la poubelle

Un code ne marchera jamais,il n'a jamais reçu la capacité de se déplacer.
Inutile donc de dire "ça marche pas", donnez plûtot des informations précises afin de mieux pouvoir vous aider.


Grand gourou de la -attitude - Sauvons Internet!
supersnail est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/06/2011, 17h09   #3
Modérateur
 
Avatar de Obsidian
 
Homme
Chercheur d'emploi
Inscription : septembre 2007
Messages : 3 701
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 36
Localisation : France, Essonne (Île de France)

Informations professionnelles :
Activité : Chercheur d'emploi
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : septembre 2007
Messages : 3 701
Points : 7 247
Points : 7 247
Bonjour !

Alors, dans le désordre :

Tu peux voir directement le code assembleur produit par GCC avec l'option « -S ». C'est très instructif, surtout en fonction des différents niveaux d'optimisation « -O » ;

Pour le reste, les exceptions CPU et les exceptions C++ ne sont pas du tout les mêmes. Elles portent le même nom car il s'agit de traiter le même genre de problème, mais chacun à leur niveau. Dans le cas de la division, le calcul est effectué électroniquement par le micro-processeur lorsqu'il dispose d'une instruction pour le faire (cas des x86) sauf bien sûr dans le cas où le diviseur est nul. Tous les nombres peuvent donc être traités à l'exception de ce cas précis.

C'est d'ailleurs de là que vient le terme : il s'agit de gérer les situations qui font exception à la règle générale de traitement. Mais avec la « jargonisation » des notions informatiques et avec la programmation orientée objet, « l'exception » est devenue une sorte d'entité, et c'est elle que l'on traite, plutôt que la situation dans laquelle on se trouve. C'est un abus de langage, comme en ont été victimes les notions de « registre » ou de « vecteur » par exemple.

Quoi qu'il en soit, le micro-processeur ne peut pas honorer l'instruction qui lui a été donné et ça, ce n'est pas un cas prévu de manière générale au niveau de l'assembleur : les instructions ne renvoient pas de « code d'erreur » ou de statut comme une fonction en C. Elles sont censées fonctionner tout le temps. Donc, dans ce cas de figure identifié mais en dehors du cadre normal de traitement, le micro-processeur va appeler une de ses interruptions, comme indiqué sur cette page :

http://support.microsoft.com/kb/117389

Donc, dans le cas d'une division par zéro, le micro-processeur va automatiquement faire l'équivalent de « int 00h ». À charge du concepteur du système d'exploitation de placer derrière cette interruption une routine permettant au programme de se terminer si nécessaire et de ramener le système dans le dernier état stable connu.

À noter que tous les cas de figure d'exception identifiés, au niveau de du micro-processeur, donnent lieu à un appel similaire et que le vecteur utilisé est défini « en dur » par le concepteur de la puce (ici Intel). Tu ne peux donc pas mapper le traitement de la division par zéro sur un autre vecteur que celui de « int 00h ».

Tout cela n'est vrai que pour ce qui concerne directement le micro-processeur. Si tu fais une division « logicielle » par 0, autrement dit si tu utilises une routine effectuant le calcul, c'est ton logiciel qui va s'apercevoir que le diviseur est nul et qui va s'orienter ensuite vers la procédure de son choix.


En ce qui concerne le C++ à présent, une exception est traitée comme une sortie de bloc, telle que tu la ferais avec break ou return. Autrement dit, on interrompt la séquence en cours et on saute directement à l'endroit où l'on va être capable de retomber sur ses pieds. Ça veut dire qu'il s'agit d'un goto, celui-là même qu'on t'enseigne en général à ne jamais utiliser. C'est d'ailleurs un des rares cas où on l'utilise en C.

Par contre, on voit que les exceptions C++ sont gérées par lui-même et ne sont en aucune façon l'affaire du micro-processeur.

À noter enfin que « throw new Exception », c'est plus du Java que du C++ (même si ça reste valide dans une certaine mesure). D'abord, le C++ peut lancer n'importe quelle donnée. Par exemple, tu peux très bien lancer un entier en faisant « throw 5 » et « catch (int) ». Ensuite, si tu utilises new, il faudra explicitement rattraper ce pointeur et effacer l'objet concerné avec delete.

Tu pourrais donc très bien te contenter de lancer un numéro de séquence, voire même tout simplement l'état du pointeur de programme (soit l'adresse de l'instruction en cours d'exécution). L'intérêt de lancer un objet dans ce cas précis est principalement la possibilité d'utiliser l'héritage : si le cas de figure ne peut pas être traité au niveau local, il pourra l'être à un niveau plus général si tu utilises des catch imbriqués. Et la possibilité de spécialiser les problèmes de manière de plus en plus fine se prête bien à ce genre de traitement.
Obsidian est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/06/2011, 20h44   #4
Invité régulier
 
Inscription : juin 2010
Messages : 4
Détails du profil
Informations forums :
Inscription : juin 2010
Messages : 4
Points : 7
Points : 7
Alors merci beaucoup.

J'ai lu la sortie asm de g++, et les exceptions c++ sont en effet gérées par du code supplémentaire sur mon linux i686, et j'ai été très con de poser la question sur les exceptions matérielles, le systeme balance un signal SIGFPE au processus qui fait une division par zero, tout comme une SIGSEGV pour les segfaults, alors que les exceptions c++ (throw, try, catch) sont en fait gérées par des subroutines que le compilateur rajoute (c'est incroyable tout ce que ce compilo peut rajouter en fait !).

En gros pour chopper une "floating point exception", qui inclus l'exception de division par zéro, il doit falloir écrire un gestionnaire de signaux, ce qui est complètement différent.

L'implémentation des exceptions c++ (fonctions d'allocation, de lancement, de recuperation) sous Linux est fortement ressemblante à l'implémentation Windows, j'ai trouvé l'explication complete sur http://www.codesourcery.com/public/c...h.html#cxx-abi, après il est possible que la lib qui gère çà change avec les archis, mais çà correspond à la mienne. Je ne me suis pas encore plongé dedans, mais je compte le faire, j'ai juste vu vite fait que les exceptions étaient allouées sur le tas, et organisées en listes châinées comme sur Win.
artefactman est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 13/06/2011, 00h33   #5
Modérateur
 
Avatar de Obsidian
 
Homme
Chercheur d'emploi
Inscription : septembre 2007
Messages : 3 701
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 36
Localisation : France, Essonne (Île de France)

Informations professionnelles :
Activité : Chercheur d'emploi
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : septembre 2007
Messages : 3 701
Points : 7 247
Points : 7 247
Citation:
Envoyé par artefactman Voir le message
Alors merci beaucoup. J'ai lu la sortie asm de g++, et les exceptions c++ sont en effet gérées par du code supplémentaire sur mon linux i686, et j'ai été très con de poser la question sur les exceptions matérielles, le systeme balance un signal SIGFPE au processus qui fait une division par zero, tout comme une SIGSEGV pour les segfaults,
Au contraire, la question est pertinente et il est important de faire le distingo. Cela dit, le système envoie SIGFPE ou SIGSEGV parce que le micro-processeur a lui-même déclenché une exception matérielle. Le système pouvant par ailleurs envoyer d'autres signaux qui ne sont nullement liés au matériel.

Citation:
alors que les exceptions c++ (throw, try, catch) sont en fait gérées par des subroutines que le compilateur rajoute (c'est incroyable tout ce que ce compilo peut rajouter en fait !).
Oui, mais justement, ce n'est pas à proprement parler du code « caché » : il faut considérer les exceptions C++ comme des goto explicites vers le premier bloc dont la signature correspond à celle de l'objet lancé.

Citation:
En gros pour chopper une "floating point exception", qui inclus l'exception de division par zéro, il doit falloir écrire un gestionnaire de signaux, ce qui est complètement différent.
Certes, mais sous certaines conditions, tu peux lancer une exception depuis le gestionnaire.
Obsidian est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 00h52.


 
 
 
 
Partenaires

Hébergement Web