IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Programmation d'OS Assembleur Discussion :

Appel d'une fonction C depuis un fichier ASM


Sujet :

Programmation d'OS Assembleur

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    36
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 36
    Points : 22
    Points
    22
    Par défaut Appel d'une fonction C depuis un fichier ASM
    Bonjour à tous,

    Je sais que la question à dû déjà être traitée sous toutes ses coutures, mais pour l'instant je bloque dans mes recherche...

    Voici l'idée :

    Je dispose d'un code ASM (je l'ai adapté d'un fichier qui n'est pas de moi (source : TutoOS.Bootsect)) : c'est un secteur de boot qui appelle la fonction "puissance" écrite dans un fichier C.

    Voici les fichiers en question :

    Le fichier ASM : (compilateur : nasm) les deux rajouts important sont marqué par des commentaires. De plus ces parties nouvelles ont sûrement des erreurs, donc n'hésitez pas à me corriger...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
     
    [BITS 16] ; indique a nasm que l'on travaille en 16 bits
    [ORG 0x0]
     
    ; initialisation des segments en 0x07C00
    mov ax, 0x07C0
    mov ds, ax
    mov es, ax
    mov ax, 0x8000
    mov ss, ax
    mov sp, 0xf000 ; stack de 0x8F000 -> 0x80000
     
    ; rajout : on fait l'opération
    push 4
    push 5
    call puissance
    pop ax
     
    ; rajout : on verifie le resultat
    cmp ax, 1024
    jne .end
     
    ; affiche un message
    mov si, message
    call afficher
     
     
    end:
    jmp end
     
     
    ;--- Variables ---
    message db "4 puissance 5 vaut bien 1024", 13, 10, 0
    ;-----------------
     
    ;---------------------------------------------------------
    ; Synopsis: Affiche une chaine de caracteres se terminant par 0x0
    ; Entree: DS:SI -> pointe sur la chaine a afficher
    ;---------------------------------------------------------
    afficher:
    push ax
    push bx
    .debut:
    lodsb ; ds:si -> al
    cmp al, 0 ; fin chaine ?
    jz .fin
    mov ah, 0x0E ; appel au service 0x0e, int 0x10 du bios
    mov bx, 0x07 ; bx -> attribut, al -> caractere ascii
    int 0x10
    jmp .debut
     
    .fin:
    pop bx
    pop ax
    ret
     
    ;--- NOP jusqu'a 510 ---
    times 510-($-$$) db 144
    dw 0xAA55
    Et voici le code C (compilateur : gcc), qui celui-là, bien que pas optimisé, est juste !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    short int puissance(short int nombre, short int exposant)
    {
    	int compteur, resultat=1;
    	for(compteur=0 ; compteur<exposant ; compteur++)
    		resultat *= nombre;
    	return resultat;
    }
    Voilà tout au niveau des sources.
    Maintenant, j'aimerais savoir comment on peut faire le lien entre les deux bouts de code.

    Merci d'avance pour vos réponses !

  2. #2
    Membre confirmé Avatar de bifur
    passe le balais et l'aspirateur
    Inscrit en
    Mars 2008
    Messages
    314
    Détails du profil
    Informations personnelles :
    Âge : 38

    Informations professionnelles :
    Activité : passe le balais et l'aspirateur

    Informations forums :
    Inscription : Mars 2008
    Messages : 314
    Points : 550
    Points
    550
    Par défaut
    c'est compiler les deux dans le même programme qui t'interesse?, a priori c'est gcc qui doit être capable de compiler un programme en C avec de l'assembleur dedans. même si le C est minoritaire dans ton cas

    sinon pour la fonction puissance je me seraispas embêté avec du C et j'aurais plutôt fait:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    puissance: ;in: ax=nombre cx=exposant out ax=résultat
    push cx
    push dx
    mov ax,1
    xor dx,dx ;met dx a zéro
    cmp cx,0
    je finpuissance
    bouclepuissance:
    mul bx
    dec cx
    jnz bouclepuissance
    finpuissance:
    pop dx
    pop cx
    ret
    et une dernière chose, toujours dépiler ce qui a été empilé sinon la taille de la pile grandit sans que ce soit utile

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    36
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 36
    Points : 22
    Points
    22
    Par défaut
    Pour ce qui est de la version ASM de la fonction, je te remercie, ça me donne l'occasion de lire de l'asm pas trop compliqué. Par contre j'aimerai qui ce soit l'asm qui appelle le c, et pas l'inverse.

    En fait, je pensais plutôt à quelque-chose du style : je compile indépendamment les deux codes, puis je me débrouille pour que l'asm sache où trouver la fonction puissance. Un peu comme les .exe qui appellent des fonction externes (printf par exemple).

    Voilà tout, en espérant être clair.

  4. #4
    Membre confirmé Avatar de bifur
    passe le balais et l'aspirateur
    Inscrit en
    Mars 2008
    Messages
    314
    Détails du profil
    Informations personnelles :
    Âge : 38

    Informations professionnelles :
    Activité : passe le balais et l'aspirateur

    Informations forums :
    Inscription : Mars 2008
    Messages : 314
    Points : 550
    Points
    550
    Par défaut
    il te faudrait une fonction include dans ton prog assembleur mais pour les fichier binaires comme ça tu pourrais mettre ton prog asm ton code C (ou autre) déja compilé. par contre je ne pense pas que ça existe sous nasm (mais je peut me tromper)

    ou alors il faudrait créer une sorte de décompilateur qui transformerais un fichier binaire en un fichier texte du format code assembleur (avec que des instruction db XX) pour que ce soit transparent au niveau du compilateur assembleur

    par contre la c'est moi qui n'est plus clair

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    36
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 36
    Points : 22
    Points
    22
    Par défaut
    Ok, merci pour ces réponses.

    De mon coté, j'ai trouvé ce lien, et le mot clé extern m'as bien l'air d'être la solution à mon problème.

    Sinon, je comprends ta dernière idée de décompresser et de retrouver les instruction asm de la fonction codée en C, mais ça m'à l'air d'être une méthode franchement barbare...

    Je continue mes recherches et je vous tiens au courant

  6. #6
    Membre actif
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    169
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 169
    Points : 251
    Points
    251
    Par défaut
    Salut,

    Alors en fait, ça dépend de ton OS. En effet, pour appeler du code C depuis l'assembleur, tu dois lui passer les paramètres de la bonne façon : par exemple, sur la pile pour des appplis 32b, par certains registres pour des applis 64b, etc.

    Ensuite, tu dois (pour le cas de NASM), déclarer tes fonctions externes en global.

    Enfin, un petit exemple pour appeler malloc dans du code pour Linux 64b :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    section .text
    global main
    extern malloc, printf ; declarer les fonctions à appeler
    .
    .
    .
    mov	rdi, 16 ; on veut reserver 16 octets
    call	malloc ; et on a l'adresse obtenue dans rax
    .
    .
    .
    Pour compiler tout ça :


    Ça, c'est la procédure pour obtenir de l'ELF 64b. Apr̀es, pour aller plus loin et obtenir un binaire plat en 64b, je te recommande ce thread sur SO.

    Mais je vois que tu travailles en 16bits. Es-tu vraiment sûr que ce soit adapté ? Tu auras des problèmes à travailler avec des outils récents ; gcc, par exemple, produit du code 16 bits douteux. Je te conseille donc de partir sur du 32 ou du 64 bits, ce qui t'évitera pas mal d'arrachage de cheveux

  7. #7
    Membre confirmé Avatar de bifur
    passe le balais et l'aspirateur
    Inscrit en
    Mars 2008
    Messages
    314
    Détails du profil
    Informations personnelles :
    Âge : 38

    Informations professionnelles :
    Activité : passe le balais et l'aspirateur

    Informations forums :
    Inscription : Mars 2008
    Messages : 314
    Points : 550
    Points
    550
    Par défaut
    effectivement c'est barbare comme méthode, j'avais pensé a l'origine a cette solution pour insérer des fichier image directement dans l'executable (dans la partie donnée) pour éviter d'avoir besoin de fichier externes

    @CP/M ta méthode me semble bien plus adapté(et plus propre) mais lapotose semble dévelloper un secteur de boot (d'ou le code 16bit) est ce que extern mache quand même dans ce cas?

  8. #8
    Membre actif
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    169
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 169
    Points : 251
    Points
    251
    Par défaut
    Le extern n'est qu'une directive pour le linker et n'a pas d'influence sur le code généré.

    Personnellement, je conseillerais à l'OP de récupérer un secteur de boot de base (ici par exemple) et ensuite de faire toutes ses expérimentations sur un mini kernel personnalisé ; ainsi il pourra profiter de toutes les facilités du code 32/64b et donc des compilateurs modernes.

    @bifur Pour ce qui est du multifichier, si tu linkes en statique, tu peux avoir autant de librairies que tu veux, tu auras toujours un seul fichier. En fait, tu étais plus ou moins en train de réécrire un linker

  9. #9
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    36
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 36
    Points : 22
    Points
    22
    Par défaut
    Salut tout le monde

    Tout d'abord, je m'excuse pour ce retard de réponse, car j'avais complètement oublié ce sujet (honte à moi).

    Pour ce qui est du problème, je l'ai effectivement résolu en compilant de l'asm en 32bits avec gcc qui me sort un fichier binaire plat correspondant à une fonction.

    commande trouvée sur internet :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    gcc -c "%fichier%" -o "%fichier%o"
    objcopy -R .note -R .comment -S -O binary "%fichier%o" "%fichier%bin"
    avec %fichier% le chemin du fichier C

    Puis je compile avec nasm l'asm en donnant l'adresse absolu de l'endroit où sera stocké la fonction, par exemple en 0x200 (secteur suivant).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    %define ORG 0x7C00
    %define MA_FONCTION ORG+0x200
    call FONCTION
    Puis avec HxD, je me débrouille pour copier le binaire venant de l'asm en 0x0 puis le binaire venant du C en 0x200.

    Que pensez-vous de cette méthode, qui marche dans le cadre d'un secteur de boot ?

    Merci en tout cas pour vos réponses toujours très instructives.

    PS : si personne ne souhaite rajouter quelque chose dans la semaine, je mettrais le sujet en résolu.

  10. #10
    Membre averti
    Profil pro
    Inscrit en
    Mars 2013
    Messages
    397
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2013
    Messages : 397
    Points : 424
    Points
    424
    Par défaut
    J'ai pas lu tout le topique, mais c'est très simple sous Fasm.

    Il y a deux méthodes:
    - Une où Fasm va créer un fichier obj que tu dois ensuite linker via gcc ou ld.
    - Une qui va créer un elf executable directement (32 ou 64bits), donc sans passer par gcc, et très compact. C'est la méthode que j'utilise.

    Nasm c'est pas ce qu'il y a de plus simple pour débuter.
    C'est pas ce qu'il y a de plus simple tout court d'aileurs.
    En faite je n'aime pas Nasm tout simplement : )

    L'exemple pour les deux solutions de Fasm se trouve dans le répertoire example de l'archive du programme.
    Il y a aussi un exemple plus détaillé pour la solution 1 ici:
    http://flatassembler.net/examples/flibc.zip

  11. #11
    Membre actif
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    169
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 169
    Points : 251
    Points
    251
    Par défaut
    Je n'ai pas le temps de tester, mais tu ne peux pas tout simpement faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    gcc -c fichier.c fichier.asm -o fichier.o
    objcopy -O binary fichier.o fichier.bin
    Comme ça gcc s'occupe de tout linker comme il faut et tu n'as pas besoin de tripatouiller les binaires à la main

Discussions similaires

  1. appel d'une fonction contenu dans un fichier js
    Par geoman dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 24/08/2007, 07h51
  2. [Debutant] Appel d'une fonction FORTRAN depuis C++
    Par Amariel dans le forum Débuter
    Réponses: 2
    Dernier message: 10/07/2007, 13h14
  3. Appel d'une fonction A depuis une fonction B.
    Par LeFlou dans le forum C++
    Réponses: 9
    Dernier message: 22/05/2007, 17h36
  4. [Compilation] Appel d'une fonction C++ depuis du code C
    Par bladerunners dans le forum C++
    Réponses: 1
    Dernier message: 06/09/2006, 14h26
  5. Appel d'une fonction pour renommer un fichier
    Par navis84 dans le forum Général JavaScript
    Réponses: 5
    Dernier message: 13/04/2006, 15h13

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo