C'est la solution la plus pratique. Consultez la documentation
de gcc et prenez exemple sur les sources du noyau Linux (fichiers
.S qui sont utilisés avec gas, non pas
as86).
Les arguments 32 bits sont empilés dans la pile vers le
bas dans l'ordre inverse de l'ordre syntaxique (c'est-à-dire
qu'on accède aux arguments ou les dépile dans l'ordre
syntaxique), au-dessus de l'adresse de retour 32 bits.
%ebp, %esi, %edi,
%ebx doivent être conservés par
l'appelé, les autres registres peuvent être
détruits; %eax doit contenir le résultat,
ou %edx:%eax pour des résultats sur 64
bits.
Pile virgule flottante: je ne suis pas sûr, mais je pense
que le résultat se trouve dans st(0), la pile
étant à la discrétion de l'appelé.
Notez que GCC possède certaines options pour modifier les conventions d'appel en réservant certains registres, en mettant les arguments dans des registres, en supposant que l'on ne possède pas de FPU, etc. Consultez les pages .info concernant le i386.
Il faut prendre garde à déclarer l'attribut
cdecl pour une fonction qui suit la convention
standard GCC (je ne sais pas exactement ce que cela produit avec
des conventions modifiées). Consultez la documentation GCC
dans la section: C Extensions::Extended Asm::
Certains compilateurs C ajoutent un underscore avant tout symbole, alors que d'autres ne le font pas.
En particulier, la version GCC a.out effectue ce genre d'ajouts, alors que la version ELF ne le fait pas.
Si vous êtes confronté à ce problème, regardez comment des paquetages existants traitent le problèmes. Par exemple, récupérer une ancienne arborescence des sources de Linux, Elk, les qthreads ou OCAML...
Vous pouvez également redéfinir le renommage implicite de C en assembleur en ajoutant les instructions suivantes:
void truc asm("machin") (void);
Remarquez que l'outil objcopy, du paquetage
binutils, devrait vous permettre de transformer vos
fichiers objets a.out en objets ELF et peut-être inversement
dans certains cas. D'une manière plus générale, il
vous permet d'effectuer de nombreuses conversions de formats de
fichiers.
Il n'est absolument pas recommandé d'effectuer de tels
appels par ce que leurs conventions peuvent changer de temps en
temps, ou d'un type de noyau à un autre (cf L4Linux), de
plus, ce n'est pas portable, difficile à écrire,
redondant avec l'effort entrepris par libc, et enfin, cela
empêche les corrections et les extensions effectuées
à travers la libc, comme par exemple avec le programme
zlibc qui réalise une décompression à
la volée de fichiers compressés avec gzip. La
manière standard et recommendée d'effectuer des appels
systèmes est et restera de passer par la libc.
Les objets partagés devraient réduire l'occupation
mémoire des programmes, et si vous souhaitez absolument
avoir de petits exécutables, utilisez #! avec
un interpréteur qui contiendra tout ce que vous ne voulez
pas mettre dans vos binaires.
Maintenant, si pour certaines raisons, vous ne souhaitez pas effectuer une édition des liens avec la libc, récupérez-la et essayez de comprendre comment elle fonctionne! Après tout, vous prétendez bien la remplacer non?
Vous pouvez aussi regarder comment eforth 1.0c le fait.
Les sources de Linux sont fort utiles, en particulier le fichier d'en-tête asm/unistd.h qui décrit comment sont effectués les appels système...
Le principe général est d'utiliser l'instruction
int $0x80 avec le numéro de l'appel
système __NR_machin (regarder dans
asm/unistd.h) dans %eax, et les
paramètres (jusqu'à cinq) dans %ebx,
%ecx, %edx, %esi,
%edi. Le résultat est renvoyé dans
%eax avec un résultat négatif étant
l'erreur dont l'opposé est tranféré par la libc
dans errno. La pile utilisateur n'est pas modificée donc
n'avez pas besoin d'en avoir une correcte lors de l'appel.
Si vous souhaitez effectuer des entrées/sorties
directement sous Linux, soit il s'agit de quelque chose de
très simple qui n'a pas besoin de spécificités du
système et dans ce cas là, consultez le mini-HOWTO
IO-Port-Programming, ou alors vous devez créer
un nouveau gestionnaire de périphérique et vous devriez
alors lire quelques documents sur les méandres du noyau, le
développement de gestionnaires de périphériques,
les modules du noyau, etc. Vous trouverez d'excellents HOWTO ou
autres documents du projet LDP.
Plus particulièrement, si vous souhaitez réaliser des programmes graphiques, rejoignez le projet GGI: http://synergy.caltech.edu/~ggi/ http://sunserver1.rz.uni-duesseldorf.de/~becka/doc/scrdrv.html
Dans tous les cas, vous devriez plutôt utiliser l'assembleur en ligne de GCC avec les macros provenant des fichiers linux/asm/*.h que d'écrire des sources en assembleur pur.
De telles choses sont théoriquement possibles (preuve: voir comment DOSEMU permet à des programmes d'accéder au port série), et j'ai entendu des rumeurs que certaines personnes le font (avec le gestionnaire PCI? Accès aux cartes VESA? PnP ISA? Je ne sais pas). Si vous avez de plus amples précisions à ce sujet, soyez les bienvenus. Le bon endroit à regarder est les sources du noyau, les sources de DOSEMU (et des autres programmes se trouvant dans le répertoire DOSEMU ), ainsi que les sources d'autres programmes bas niveaux (peut-être GGI s'il gère les cartes VESA).
En fait, vous devez utiliser soit le mode protégé 16 bits, soit le mode vm86.
Le premier est plus simple à configurer mais il ne fonctionne qu'avec du code ayant un comportement propre qui n'effectue pas d'arithmétique de segments ou d'adressage absolu de segment (en particulier pour l'adressage du segment 0), à moins que par chance tous les segments utilisés peuvent être configuré à l'avance dans le LDT.
La seconde possiblité permet d'être plus "compatibles" avec les environnements 16 bits mais il nécessite une gestion bien plus compliquée.
Dans les deux cas, avant de sauter sur le code 16 bits, vous devez:
Encore une fois, lisez attentivement les codes sources situés dans le répertoire de DOSEMU et consorts, en particulier ces mini-émulateurs permettant de faire tourner des programmes ELKS et/ou des .COM assez simples sous Linux/i386.
La plupart des émulateurs DOS sont livrés avec
certaines interfaces d'accès aux services DOS. Lisez leur
documentation à ce sujet, mais bien souvent, ils ne font que
simuler int $0x21 et ainsi de suite, donc c'est
comme si vous étiez en mode réel (je doute qu'ils aient
de possibilités de fonctionner avec des opérandes 32
bits: ils ne font que réfléchir l'interruption dans le
mode réel ou dans le gestionnaire vm86).
Certaines documentations concernant DPMI (ou ses variantes peuvent) être trouvées sur ftp://x2ftp.oulu.fi/pub/msdos/programming/
DJGPP est livré avec son propre sous-ensemble, dérivé, ou remplacement (limité) de la glibc.
Il est possible d'effectuer une compilation croisée de Linux vers DOS. Consultez le répertoire devel/msdos/ de votre miroir FTP de sunsite.unc.edu. Voir également le dos-extender MOSS du projet Flux d'utah.
D'autres documentations et FAQ sont plus consacrés à DOS. Nous déconseillons le développement sous DOS.
Heu, ce document ne traite que de libre logiciel. Téléphonez-moi lorsque Windaube le deviendra ou du moins ses outils de développement!
En fait, après tout, cela existe: Cygnus Solutions a développé la bibliothèque cygwin32.dll pour que les programmes GNU puissent fonctionner sur les machines MicroMerdiques. Donc, vous pouvez utiliser GCC, GAS et tous les outils GNU ainsi que bon nombre d'applications Unix. Consultez leur site Web. Je (Faré) ne souhaite pas m'étendre sur la programmation sous Windaube, mais je suis sûr que vous trouverez tout un tas d'informations partout...
Le contrôle sur le système étant ce qui attire de nombreux programmeurs vers l'assembleur, une prémisse ou un corollaire naturel de son utilisation est la volonté de développer son propre système d'exploitation. Remarquons tout d'abord que tout système permettant son auto-développement pourrait être qualifié de système d'exploitation, combien même tournerait-il au-dessus d'un autre système sur lequel il se déchargerait de la gestion du multitâche (Linux sur Mach) ou des entrées/sorties (OpenGenera sur Digital Unix), etc. Donc, pour simplifier le débogage, vous pouvez souhaiter développer votre système d'exploitation comme étant un processus fonctionnant sous Linux (au prix d'un certain ralentissement), puis, utiliser le Flux OS kit (qui permet l'utilisation des drivers Linux et BSD dans votre propre système d'exploitation) pour le rendre indépendant. Lorsque votre système est stable, il est toujours temps d'écrire vos propres gestionnaires de matériels si c'est vraiment votre passion.
Ce HowTo ne couvrira pas des sujets comme le code de chargement du système, le passage en mode 32 bits, la gestion des interruptions, les bases concernant les horreurs des processeurs Intel (mode protégé, V86/R86), la définition de votre format d'objets ou de vos conventions d'appel. L'endroit où vous pourrez trouver le plus d'informations concernant tous ces sujets est le code source de système déjà existants.
Un grand nombre de pointeurs se trouvent dans la page: http://www.eleves.ens.fr:8080/home/rideau/Tunes/Review/OSes.html
Chapitre suivant, Chapitre Précédent
Table des matières de ce chapitre, Table des matières générale
Début du document, Début de ce chapitre