C'est la solution la plus pratique.
Les arguments 32 bits sont empillés dans l'ordre inverse
(de là, dépillés dans le bon ordre) au-dessus de l'adresse de retour
32 bits. Les registres %ebp, %esi, %edi
et %ebx
sont préservés. %eax
contient le résultat,
ou bien %edx:%eax
dans le cas d'un résultat sur 64 bits.
Pile FP
: je ne suis pas très sûr, mais je pense
que son résultat se trouve dans st(0)
, toute la
pile d'appel étant conservée.
gcc
possède certaines options pour modifier les
conventions d'appels en réservant des registres, mettant des arguments
dans des registres, ne pas gérer la FPU. Consultez les documents
sur le i386.
Faites attention à bien déclarer une fonction asmlinkage
si vous voulez que gcc
utilise la convention standard
(je ne sais pas trop ce qu'il fait avec les conventions modifiées).
Quelques compilateurs C rajoutent un blanc souligné avant chaque symbole, alors que d'autres ne le font pas.
En particulier, gcc
a.out pour Linux effectue ce genre
de rajout, alors que la version ELF ne le fait pas.
Regardez comment le noyau gère cela
(linux/include/linux/linkage.h
).
Vous pouvez redéfinir la procédure de renomage C vers assembleur en insérant des expressions comme
void truc asm("zorglub") (void);pour s'assurer que la fonction C
truc
sera appelée
zorglub
en assembleur.
Vous pouvez remarquer que l'utilitaire objcopy
du paquetage
binutils
devrait vous permettre de transformer vos
objets a.out en objets au format ELF, et peut-être même le
contraire dans certains cas.
Ce n'est pas vraiment recommandé car cela peut changer, et surtout
parceque ce n'est pas portable. Enfin, ce n'est vraiment pas conseillé
car la bibliothèque libc effectue certaines corrections ainsi que
certaines extensions, comme par exemple zlibc
(qui effectue de la décompression à la volée de fichiers compressés avec
gzip
). Par convention, il est recommandé
d'utiliser la libc pour faire appelle à appels systèmes.
Maintenant, si vous ne voulez pas effectuer une édition de liens avec
la libc, alors vous devriez regarder comment
linux-eforth-1.0c.tgz
le fait
(ftp://ftp.forth.org/pub/Forth/Linux/).
Les sources de Linux sont bien utiles, en particulier
le fichier d'en-tête asm/unistd.h
, qui décrit comment
effectuer des appels systèmes...
D'une manière plus pratique, vous appellez l'intéruption
$0x80, avec le nombre __NR_syscallname
(voir
asm/unistd.h
)
dans le registre %eax
, et les paramètres
(cinq maximum) se trouvent respectivement
dans les registres %ebx, %ecx, %edx, %esi, %edi
.
La valeur de retour se trouve dans le registre
%eax
, et si le nombre est négatif, alors
il s'agit d'une erreur que la libc va transformer en
errno
. La pile utilisateur n'est pas modifiée, donc ce n'est
pas la peine d'en avoir une valide lors de l'appel système.
Bon nombre d'extensions DOS sont fournies avec des services DOS. Lisez leur documentation, mais bien souvent, ils ne font que simuler l'interruption 0x21 et ainsi de suite, comme si vous étiez en mode réel (je doute que cela marche avec des opérateur 32 bits en appellant des services du DOS en 16 bits).
La documentation concernant DPMI ou autres se trouve sur ftp://x2ftp.oulu.fi/pub/msdos/programming/.
DJGPP est fournis avec sa propre libc (limitée).
Il est possible d'effecter une cross-compilation de Linux vers
Dos, mais les patches existants ont été écrit pour la version a.out
de gcc
. Peut-être que les dernières versions ELF du compilateur
n'ont pas besoin d'être patchées : je n'en sais rien.
La source principale d'information est les sources des systèmes d'exploitations existant. Bon nombre de pointeurs se trouve sur la page WWW suivante : 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