Forum Programmation.autre Assembleur inline dans gcc

Posté par (page perso) .
Tags : aucun
0
5
avr.
2007
Salut à tous !
Je suis en train de me galérer pour 3 pauvres lignes d'assembleur à intégrer dans du code C... Est-ce que quelqu'un sait si gcc sauvegarde/restaure automatiquement le contexte ?

Par exemple, si j'écris:
asm("movw $0x6f09, %ax");
Est-ce que je suis sûr que je ne vais pas écraser une donnée qui a été mise précédemment dans le registre ax par le compilateur C ?
A priori non, mais je voudrais être sûr...

Ensuite, je dois faire un appel à une interruption:
asm("int $0x15");
C'est celle qui est documentée sur la carte mère: cela fait un appel au BIOS de la carte pour récupérer/envoyer des valeurs sur des entrées/sorties numériques. Mais ça plante sur un segfault, et je ne sais absolument pas pourquoi ! Pire encore, je ne sais pas comment je peux le savoir ! J'ai vérifié que les I/O de la carte étaient activées dans le BIOS, mais malgré tout, dès que j'appelle l'interruption, boum, plantage...

Quelqu'un aurait une piste, ne serait-ce que pour une manière de déboguer ce qui se passe ?

Merci
  • # L'asm, le DOS, les démos, le mode X, love them !

    Posté par . Évalué à 3.

    Est-ce que je suis sûr que je ne vais pas écraser une donnée qui a été mise précédemment dans le registre ax par le compilateur C ?


    Il y a peu de chance. Le C ne fait pour ainsi dire que des appels de fonctions, donc de l'une à l'autre ... à part si tu as passé des options d'optimisation spéciales (il y en a une qui tente de passer le maximum d'infos dans les registres plutôt que dans la pile).

    Si tu crains quelque chose, essaie versatile et register, sachant que c'est sans garantie.

    Mais ça plante sur un segfault, et je ne sais absolument pas pourquoi ! Pire encore, je ne sais pas comment je peux le savoir ! J'ai vérifié que les I/O de la carte étaient activées dans le BIOS, mais malgré tout, dès que j'appelle l'interruption, boum, plantage... Quelqu'un aurait une piste, ne serait-ce que pour une manière de déboguer ce qui se passe ?


    Il n'y a aucune chance que ce que tu comptes faire fonctionne, car il y a longtemps que tous les systèmes d'exploitation fonctionnent en mode protégé.

    D'une manière générale, ton application fonctionne dans un environnement partagé par plusieurs autres ressources, donc tu ne peux pas aller modifier comme ça l'état de ta machine sans en référer au système. Si tu veux bidouiller les fonctions du BIOS, tu as deux options :

    - Tu démarres sous DOS (voir http://www.freedos.org/ )
    - Tu fais des exécutables bootables, tu les colles sur les premiers secteurs d'une disquette et tu démarres dessus.

    Je t'encourage cependant fortement dans cette voie, car les jeunes coders qui débutent aujourd'hui ne peuvent absolument plus se rendre compte de la manière dont fonctionne leur machine. Par contre, si tu fais appel aux fonctions du BIOS et que ton accumulateur ax n'est même pas encore un eax, c'est que ton bouquin doit être assez vieux, maintenant.
    • [^] # Re: L'asm, le DOS, les démos, le mode X, love them !

      Posté par (page perso) . Évalué à 3.

      Merci pour ta réponse. Bin en fait je dois faire tourner l'ppli sous Fedora Core 6, donc DOS c'est mort, pareil pour un exe bootable.

      Pour ce qui est de eax, c'est juste que j'avais besoin que de 16bits, donc j'ai utilisé ax qui fait exactement cette taille.
      Regarde page 50 de ce document, c'est ce qu'on me dit d'utiliser:
      http://files.ieiworld.com/files/IEINET/andyliu/2005/08/12/09(...)

      J'avoue que je ne sais pas comment fonctionne le mode protégé du processeur, mais il doit bien y avoir une autre manière que celles que tu as indiqué quand meme ?

      J'aimerais bien faire appel à un vecteur d'interruption bateau pour voir si ça plante aussi, mais je ne sais pas lequel je suis autorisé à appeler...

      PS: Le jeune codeur a 27 ans quand même ;-)
      • [^] # Re: L'asm, le DOS, les démos, le mode X, love them !

        Posté par . Évalué à 2.

        J'aimerais bien faire appel à un vecteur d'interruption bateau pour voir si ça plante aussi, mais je ne sais pas lequel je suis autorisé à appeler...


        Ça plantera, crois-moi sur parole ! :-)

        J'avoue que je ne sais pas comment fonctionne le mode protégé du processeur


        http://charles.moostik.net/pmode/index.php3?page=Introductio(...)

        mais il doit bien y avoir une autre manière que celles que tu as indiqué quand meme ?


        Il y en a une, mais ce n'est pas riant : écrire un module du noyau.

        Note que le problème resterait exactement le même sous Windows ou sous tout autre OS multitâche. Le bon coté, c'est que le boulot à faire est relativement simple (pas comme si on faisait un pilote de disque ou vidéo). Le mauvais, c'est que si ton programme plante, c'est pas une segfault que va affronter, mais un plantage général du système.

        La vraie difficulté, à mon avis, viendra du fait qu'il faudra probablement repasser en mode réel pour appeler la fonction du BIOS, puis revenir en mode protégé et restaurer tout l'état du système.

        Le plus triste, c'est que cette interruption doit probablement se contenter de faire un out bien placé vers un port d'entrée/sortie et que pour faire la même chose sous Linux, un bête ioperm suffit à un processus utilisateur ordinaire (root) pour faire le boulot ! :-)
  • # BIOS ?

    Posté par . Évalué à 4.

    Tu veux faire quoi exactement qui t'oblige à passer par le BIOS ?
    J'ai l'impression que tu veux accéder à un périphérique hard sans passer par un driver...
    A mon avis, tu risque de devoir, soit d'écrire un driver, soit réutiliser une driver existant de Linux. Je ne pense pas que l'assembleur soit vraiment nécessaire ensuite.
    • [^] # Re: BIOS ?

      Posté par . Évalué à 1.

      Alors la je plussoie violament la remarque precedante.

      Est-ce que je suis sûr que je ne vais pas écraser une donnée qui a été mise précédemment dans le registre ax par le compilateur C ?

      C'est quasi certain que tu l'ecrase oui, l'assembleur inline n'est pas encadré par des push/pop. Pour le voir demande a gcc de generer et laisser le code pseudo-assembleur du code en C pour voir ca.

      ... ça plante sur un segfault, et je ne sais absolument pas pourquoi ! Pire encore, je ne sais pas comment je peux le savoir ! J'ai vérifié que les I/O de la carte étaient activées dans le BIOS, mais malgré tout, dès que j'appelle l'interruption, boum, plantage...
      Sous linux l'espace memoire est partagé en deux, user et kernel. Le user-space n'as aucun acces direct au ressource physique du systeme, aucun acces au hard ou a la memoire il doit passer par le kernel pour demander l'acces ou les operation permise(par un driver).
      Sur toutes les machines, quand on execute un programme en espace user la tentative d'utilisation des certaines instructions assembleurs provoque un exeception qui se traduit ensuite par un segfault, c'est typiquement ce qu'il se passe quand tu fais asm("int $0x15");
      int est une instruction du mode protégé qui ne peut pas etre executé quand le run-level du proc est "user".
      Si tu veut plus d'info sur le driver a ecrire post dans le forum kernel
      • [^] # Re: BIOS ?

        Posté par (page perso) . Évalué à 2.

        Hum... Ça commence à me faire peur... Ça voudrait dire que j'ai besoin d'un driver spécifique, non fourni avec la carte par le constructeur. Je me demandais comment des applications comme gnome-power-manager faisaient pou communiquer avec l'ACPI, qui est géré avec des appels au BIOS... Ce serait le noyau qui fait les appels par l'intermédiaire d'un driver spécifique à la carte, ou alors ce sont des appels à des trucs comme hal qui sera l'interlocuteur du noyau...? J'ai l'impression d'être pas mal à côté de la plaque sur ce coup là.
        • [^] # Re: BIOS ?

          Posté par . Évalué à 1.

          il y as driver et driver...sous linux c'est pas la mer a boire, contrairement a win et son DDK (WDM et KMDF).
          Les appli user communique avec le kernel par des fichiers speciaux situé dans /dev ou ceux dans /proc, si tu fais cat /proc/apm tu trouve les infos battery des portables par exemple...
          C'est effectivement le kernel qui redirige les interactions avec le materiel et les programme en espace user.
          Sous linux un driver c'est un module kernel (extension .ko) c'est pas tres compliqué a ecrire, la premiere des choses a faire est de lire
          http://lwn.net/Kernel/LDD3/
          ou tout est expliqué et ou les sources d'exemple fouri te permettront d'aller tres vite.
          HAL est une partie du kernel qui assume un autre role.
          • [^] # Re: BIOS ?

            Posté par (page perso) . Évalué à 2.

            J'ai vu qu'un projet utilisait cette carte:
            http://control.ee.ethz.ch/~lawrence/public-project-trac/wiki(...)


            Digital IO
            The manual for the PCISA describes how to call the DIO (4x input, 4x output) section of the PCISA board. This seems to be programmed into the BIOS; unfortunately it is not possible to call these execution routines in xPC as they run in protected mode. Thanks to the support of IEI we now have a solution which is able to read and write the DIO from within xPC. Basic drivers were written but need to be tidied up before release. Please watch this space for more details.
            • [^] # Re: BIOS ?

              Posté par (page perso) . Évalué à 2.

              Bon, apparemment tout le code là bas est pour Windows, de même que les exemples et le pilote livrés par le constructeur...
    • [^] # Re: BIOS ?

      Posté par (page perso) . Évalué à 2.

      Je dois utiliser des I/O numériques sur une carte mère JUKI 6770.
      Le manuel est ici, à la page 50 on explique comment utiliser les I/O numériques. Pour cela, on me donne comme unique solution un appel à une sous fonction du bios par un appel assembleur au vecteur d'interruption 15h.
      http://files.ieiworld.com/files/IEINET/andyliu/2005/08/12/09(...)

      Je veux bien une autre solution, mais c'est la seule donnée par le constructeur...
      MOV AX, 6F09H ;configurer le port en tant que sortie
      MOV BL, 09H ; mettre la sortie à 0x09
      INT 15H ; appeller l'interruption 0x15

      Le BIOS doit ensuite regarder la valeur du registre AX. L'octet de poids faible de AX (0x09) correspond au numéro de la sous fonction à appeler en interne au BIOS.

      Mais pas un seul exemple pour l'appeler à partir de code C, alors je me suis dit que de l'assembleur inline ferait l'affaire... Une autre solution ?
      • [^] # Re: BIOS ?

        Posté par . Évalué à 1.

        Tu vas devoir désassembler le bios.

        Récupère l'adresse du handler le l'int 15h. A partir de cette adresse tu doit avoir du code qui branche sur les fonctions (dont le code est passé dans AH : 6F). Suis le code jusqu' à la sous fonction 09. Le code qui configure les IO est à cet endroit.

        Il ne restera plus qu'à réimplémenter la même routine dans ton programme.
        • [^] # Re: BIOS ?

          Posté par . Évalué à 1.

          En suivant un lien donné plus haut j'ai trouvé le code que tu cherches en entrée 0x6F08 et en sortie 0x6F09 : http://control.ee.ethz.ch/~lawrence/public-project-trac/brow(...)

          Tu peux réimplémenter ce code en C en user mode avec des ioperm, inb et outb.
          • [^] # Re: BIOS ?

            Posté par (page perso) . Évalué à 2.

            Oui, j'avais vu ce code là, mais sans réellement savoir à quel niveau c'était exploitable, ni réellement à quoi ça correspondait... En fait je ne savais pas si c'était du code fourni par le constructeur, ou fait par gars en question.

            Effectivement, ça a l'air d'être le code qui est dans le BIOS et qui gère l'interruption 15, que le constructeur lui aurait (gentiment) donné... J'essaie de contacter ledit constructeur, pour voir s'ils auraient des pilotes Linux à me fournir. Ce gars (lawrence) les aurait contactés pour avoir ce code de gestion de l'appel BIOS + les pilotes Windows + des exemples de mise en oeuvre des pilotes Windows.

            Donc à ton avis même si le int 15h est illégal à cause du mode protégé du processeur, un accès direct au matériel est tout de même possible en user mode ? Et donc on peut se passer de driver ? En tout cas merci grandement pour cette piste, je commence à y voir plus clair...
            • [^] # Re: BIOS ?

              Posté par . Évalué à 2.

              Oui, ça devrait être possible (seulement en tant que root) grâce à ces fonctions : d'après le man, ioperm demande une "dérogation" et le kernel "autorise" l'accès direct au hard.

              Après, je pense que la meilleure solution serait de faire un vrai driver (une fois que tu auras réussi à faire ce que tu veux avec les ioperm, inb) : ça pourrait permettre à un utilisateur quelconque d'avoir accès à ce périphérique et ça permet de vérifier que le programme dans le monde user n'essaie pas de faire n'importe quoi. Et comme dit plus haut, écrire un driver, ce n'est pas si compliqué que ça (du moins pour les périphériques simples).

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.