[MIC/C/SYS] Problème avec l'inline assembly dans C

Voir le sujet précédent Voir le sujet suivant Aller en bas

resolu [MIC/C/SYS] Problème avec l'inline assembly dans C

Message  M. Pixel le Sam 19 Nov 2011, 16:05

Hello à tous,

Ça fait quelques jours que je tente d'écrire un mini-OS sur base de ce qu'on a vu en SYS2.
Je suis parvenu à faire fonctionner un petit amorceur qui charge les 9 secteurs suivants (contenant mon kernel écrit en C) et qui passe la main à ce kernel. Je fonctionne uniquement en mode réel et je fais tourner tout ça dans virtualbox.

Mais voici donc mon problème:
Je ne m'en sort pas bien lorsqu'il s'agit d'utiliser du code assembleur dans mon code C, ou plus précisément, comment faire pour que ce code fasse référence aux variables locales de la fonction (pour les variables globales, je sais utiliser offset <nomvar>, mais forcement, ça ne marche pas pour les locales qui se trouvent sur la pile).

Voici ma petite fonction print() qui prend une chaine et qui fait appèl à une interruption "maison" 0x80 qui affiche cette chaîne à l'écran en l'écrivant dans 0xB8000.
J'utilise ces fichiers source:
- main.c (contient le point d'entrée, et fait appel à print() )
- kernel.h (définition du prototype de la fonction et d'un macro)
- kernel.c (définition de la fonction print() )
Code:
void print(char * message)
{
   asm(""
      :
      : "EAX" (message)
      :);
   asm("MOV BX, 0");
   asm("INT 0x80");
}
Si EAX contient l'adresse de la chaîne terminée par '\0', tout fonctionne bien.
Seul problème... GCC compile la fonction vers ce code assembleur:
Code:
00000034  6655              push ebp
00000036  6689E5            mov ebp,esp
00000039  BB0000            mov bx,0x0
0000003C  CD80              int 0x80
0000003E  665D              pop ebp
00000040  66C3              o32 ret
Choquant, n'est-ce pas? Mon compilateur "oublie" tout simplement de faire quelque-chose du genre MOV EAX, addresse_de_message (qui aurait du se trouver à 0x39).

Mais pire encore: lorsque j'écris la fonction print() dans main.c, au lieu de kernel.c, ça marche!! Il prend alors la variable message de la pile, et la copie dans EAX.
Je tiens cependant à définir mes fonctions en dehors de main.c, autrement, je ne vous dis pas quel désordre on retrouvera dans mon main.c Sad .

Comment feriez-vous pour interagir avec des variables C à partir du inline asm?

Comme solution temporaire, j'utilise une nouvelle fonction déclarée "fastcall", et je récupère le paramètre dans les registres. Mais c'est plus lent (on passe par plusieurs push/pop), moins lisible et beaucoup moins portable (fastcall n'est pas standard, et par conséquent, mon noyau risque de ne pas fonctionner si compilé avec autre-chose que gcc... même compiler avec -Ofast fait que mes fonctions ne fonctionnent plus).

PS: Mes excuses si je n'ai pas choisi la bonne section. Un peu difficile de dire s'il s'agit de MIC, C ou SYS...

Je vous remercie d'avance!


Dernière édition par M. Pixel le Dim 20 Nov 2011, 21:43, édité 1 fois

M. Pixel

Nombre de messages : 19
Prénom : Etienne
Localisation : 0x7C00
Date d'inscription : 15/12/2010

Revenir en haut Aller en bas

resolu Re: [MIC/C/SYS] Problème avec l'inline assembly dans C

Message  M. Pixel le Dim 20 Nov 2011, 21:42

Bah je suis une fois de plus victime de ma propre distraction...

La où je précisais le registre dans lequel il faut placer la variable, il fallait donner une seule lettre représentant ce registre ("a" pour eax, "d" pour edx, "D" pour edi, etc.)!
Code:
void print(char * message)
{
  asm(""
      :
      : "a" (message)
      :);
  asm("MOV BX, 0");
  asm("INT 0x80");
}

Je ne vois pas trop comment je suis parvenu à le faire fonctionner dans main.c malgré l'erreur, mais bon... c'est Problem solved à présent.

M. Pixel

Nombre de messages : 19
Prénom : Etienne
Localisation : 0x7C00
Date d'inscription : 15/12/2010

Revenir en haut Aller en bas

Voir le sujet précédent Voir le sujet suivant Revenir en haut


 
Permission de ce forum:
Vous ne pouvez pas répondre aux sujets dans ce forum