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 Obsidian . Évalué à 3.
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.
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 liberforce (site web personnel) . Évalué à 3.
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 Obsidian . Évalué à 2.
Ça plantera, crois-moi sur parole ! :-)
http://charles.moostik.net/pmode/index.php3?page=Introductio(...)
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 Frédéric COIFFIER . Évalué à 4.
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 TheBreton . Évalué à 1.
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 liberforce (site web personnel) . Évalué à 2.
[^] # Re: BIOS ?
Posté par TheBreton . Évalué à 1.
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 liberforce (site web personnel) . Évalué à 2.
http://control.ee.ethz.ch/~lawrence/public-project-trac/wiki(...)
[^] # Re: BIOS ?
Posté par liberforce (site web personnel) . Évalué à 2.
[^] # Re: BIOS ?
Posté par liberforce (site web personnel) . Évalué à 2.
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 cj2b . Évalué à 1.
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 cj2b . Évalué à 1.
Tu peux réimplémenter ce code en C en user mode avec des ioperm, inb et outb.
[^] # Re: BIOS ?
Posté par liberforce (site web personnel) . Évalué à 2.
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 Frédéric COIFFIER . Évalué à 2.
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 à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.