Changes between Version 28 and Version 29 of Archi-1-TD10


Ignore:
Timestamp:
Nov 16, 2023, 6:18:00 PM (13 months ago)
Author:
franck
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Archi-1-TD10

    v28 v29  
    183183- C'est l'éditeur de lien qui est en charge du placement en mémoire du code et des données, et c'est dans les fichiers ldscript `kernel.ld` ou `user.ld` que le programmeur peut imposer ses choix de placement dans l'espace d'adressage.
    184184- Pour placer une fonction à une adresse précise, la méthode que vous avez vu consiste
    185   - à créer une section grâce à la directive `.section` en assembleur ou grâce à la directive `__attribute__((section()))` pour les programmes C
     185  - à créer une section grâce à la directive `.section` en assembleur ou grâce à la directive `__attribute__((section()))` pour les programmes C, dans les deux cas le programmeur choisit un nom de section.
    186186  - puis à positionner la section ainsi créée dans la description des `SECTIONS` du fichier ldscript concerné.
    187187''
    188188}}}
    189 1. Regardons comment la fonction `kinit()` appelle la fonction `_start()`, il y a deux fichiers impliqués `kinit.c` et `hcpua.S`. Pour rappel, la fonction `_start()` est la fonction d'entrée de l'application utilisateur, c'est elle qui appelle la fonction `main()`. La fonction `_start()` est donc dans le code de l'application, et non pas dans le noyau. Cependant le noyau doit connaitre son adresse afin de pouvoir y sauter et ainsi entrer dans l'application.
     1891. La première fonction d'un programme utilisateur est la fonction `_start()`, c'est elle qui appelle la fonction `main()`. La fonction `_start()` est donc dans le code de l'application, et non pas dans le noyau. Cependant le noyau doit connaitre son adresse afin de pouvoir y sauter et ainsi entrer dans l'application. \\Dans le code ci-après, nous voyons comment la fonction `kinit()` appelle cette fonction `_start()`. Deux fichiers sont impliqués `kinit.c` dans lequel se trouve la fonction `void kinit(void)` et `hcpua.S` dans lequel se trouve la fonction `void app_load(void *)` en charge d'appeler la fonction `_start()`.
    190190{{{#!c
    191191kinit.c:
     
    206206        eret 
    207207}}}
    208  Où se trouve la fonction `_start` et comment le kernel connaît-il son adresse ? (C10 S30+S32)\\
    209 {{{#!protected ------------------------------------------------------------------------------------
    210 ''
    211 - La fonction `_start` est au début de la section `.text` (code de l'utilisateur). Le noyau connait cette adresse parce qu'elle est définit dans son fichier `ldscript`.
     208 Comme le noyau et l'application sont deux exécutables compilés indépendamment, il doit y avoir une convention permettant au noyau de savoir quelle est l'adresse de `start()`.\\ Où se trouve donc la fonction `_start()` et comment le kernel connaît-il son adresse ? (C10 S30+S32)\\
     209{{{#!protected ------------------------------------------------------------------------------------
     210''
     211- La fonction `_start()` est au début de la section `.text` (qui contient le code de l'utilisateur). Le noyau connait cette adresse parce qu'elle est définit dans son fichier ldscript `kernel.ld`.
    212212''
    213213}}}
     
    215215{{{#!protected ------------------------------------------------------------------------------------
    216216''
    217 - `.globl app_load` est nécessaire parce que ce label de fonction est défini dans le fichier `hcpua.S` mais il est utilisé dans un autre (`kinit.c`).
    218 ''
    219 }}}
    220  Quels sont les registres utilisés dans le code de `app_load `?\\Que savez-vous de l'usage de `$26 `?\\Quels sont les registres modifiés ?\\Expliquez pour chacun la valeur affectée. \\
     217- `.globl app_load` est nécessaire parce que ce label de fonction est défini dans le fichier `hcpua.S` mais il est utilisé dans un autre (`kinit.c`). Il faut donc le rendre e`xtern`.
     218''
     219}}}
     220 Quels sont les registres utilisés dans le code de `app_load `?\\Que savez-vous de l'usage de `$26 `?
    221221{{{#!protected ------------------------------------------------------------------------------------
    222222''
    223223- Les registres utilisés par `app_load` sont `$4`, `$26`, `$29` du banc GPR et `$12` (`c0_sr`) et `$14` (`c0_epc`) du banc de registres du coprocesseur `0`.
    224 - `$26` est un registre GPR temporaire pour le noyau, il peut l'utiliser sans le sauver avant et donc sans le restaurer.
     224- `$26` est un registre GPR temporaire pour le noyau, il peut l'utiliser sans le sauver avant et donc sans le restaurer.
     225'''
     226}}}
     227 Quels sont les registres modifiés ? Expliquez pour chacun la valeur affectée. \\
     228{{{#!protected ------------------------------------------------------------------------------------
     229''
    225230- Il y a 4 registres affectés, dans l'ordre :
    226231  - Le registre système `$14` nommé `c0_epc`, il reçoit l'adresse `_start`, c'est-à-dire l'adresse de la fonction `_start()`.
     
    239244''
    240245}}}
    241 1. Que doit-on faire avant l'exécution de la fonction `main()` du point de vue de l'initialisation? Et au retour de la fonction `main()`? (C10 S24)
     2461. Que doit-on faire dans la fonction `_start()` avant l'exécution de la fonction `main()` du point de vue de l'initialisation? Et au retour de la fonction `main()`? (C10 S24)
    242247{{{#!protected ------------------------------------------------------------------------------------
    243248''
    244249- Comme dans la fonction `kinit()`, il faut explicitement initialiser les variables globales non initialisées dans le programme C. En effet, le programmeur suppose que les variables globales non initialisées explicitement dans le programme C sont à 0. Comme ces variables ne sont pas explicitement initialisées, elles n'occupent pas de place dans le fichier exécutable, on sait juste ou elles sont placées en mémoire.
    245 - Si on sort de la fonction `main()`, l'application s'achève. Cela signifie qu'il faut appeler la fonction `exit()` qui effectue l'appel système SYSCALL_EXIT. Cette appel est réalisé au cas où l'application n'aurait pas explicitement exécuté `exit()`. Dans ce cas la valeur rendue par l'application est la valeur de retour de la fonction `main()`.
    246 ''
    247 }}}
    248 1. Nous avons vu que le noyau est sollicité par des demandes de service, quels sont-ils? Nous rappelons que l'instruction `syscall` initialise le registre `c0_cause`, comment le noyau fait-il pour connaître la cause de son appel? (C10 S25)
     250- Si on sort de la fonction `main()`, l'application s'achève. Cela signifie qu'il faut appeler la fonction `exit()` qui effectue l'appel système SYSCALL_EXIT. Cette appel est réalisé au cas où l'application n'aurait pas explicitement exécuté la fonction `exit()`. Dans ce cas, la valeur rendue par l'application est la valeur de retour de la fonction `main()`.
     251''
     252}}}
     2531. Nous avons vu que le noyau est sollicité par des demandes de service, quels sont-ils ? Nous rappelons que l'instruction `syscall` initialise le champs `xcode` du registre `c0_cause`, comment le noyau fait-il pour connaître la cause de son appel? (C10 S25)
    249254{{{#!protected ------------------------------------------------------------------------------------
    250255''