Changes between Version 28 and Version 29 of Archi-1-TD10
- Timestamp:
- Nov 16, 2023, 6:18:00 PM (13 months ago)
Legend:
- Unmodified
- Added
- Removed
- Modified
-
Archi-1-TD10
v28 v29 183 183 - 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. 184 184 - 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. 186 186 - puis à positionner la section ainsi créée dans la description des `SECTIONS` du fichier ldscript concerné. 187 187 '' 188 188 }}} 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.189 1. 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()`. 190 190 {{{#!c 191 191 kinit.c: … … 206 206 eret 207 207 }}} 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`. 212 212 '' 213 213 }}} … … 215 215 {{{#!protected ------------------------------------------------------------------------------------ 216 216 '' 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 `? 221 221 {{{#!protected ------------------------------------------------------------------------------------ 222 222 '' 223 223 - 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 '' 225 230 - Il y a 4 registres affectés, dans l'ordre : 226 231 - Le registre système `$14` nommé `c0_epc`, il reçoit l'adresse `_start`, c'est-à-dire l'adresse de la fonction `_start()`. … … 239 244 '' 240 245 }}} 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)246 1. 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) 242 247 {{{#!protected ------------------------------------------------------------------------------------ 243 248 '' 244 249 - 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 casla 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 leregistre `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 }}} 253 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 champs `xcode` du registre `c0_cause`, comment le noyau fait-il pour connaître la cause de son appel? (C10 S25) 249 254 {{{#!protected ------------------------------------------------------------------------------------ 250 255 ''