Changes between Version 88 and Version 89 of Archi-1-TP10
- Timestamp:
- Nov 23, 2021, 6:23:29 PM (3 years ago)
Legend:
- Unmodified
- Added
- Removed
- Modified
-
Archi-1-TP10
v88 v89 170 170 '' 171 171 }}} 172 1. Que se passe-t-il quand le MIPS entre dans le noyau, après l'exécution de l'instruction `syscall`? 173 {{{#!protected ------------------------------------------------------------------------------------ 174 ''''''''''''''' 172 1. Que se passe-t-il quand le MIPS entre dans le noyau, lors de l'exécution de l'instruction `syscall`? 173 {{{#!protected ------------------------------------------------------------------------------------ 174 '' 175 Cours 10 / slide 13 175 176 - L'instruction `syscall` induit beaucoup d'opérations élémentaires dans le MIPS: 176 177 - `EPC` ← `PC` (adresse de l'instruction `syscall`) … … 178 179 - `c0_cause.XCODE` ← `8` 179 180 - `PC` ← `0x80000180` 180 '' '''''''''''''181 '' 181 182 }}} 182 183 1. Quelle instruction utilise-t-on pour sortir du noyau et entrer dans l'application ? Dîtes précisément ce que fait cette instruction dans le MIPS. 183 184 {{{#!protected ------------------------------------------------------------------------------------ 184 ''''''''''''''' 185 - C'est l'instruction `eret` qui permet de sortir du noyau. 185 '' 186 Cours 10 / slide 13\\ 187 - C'est l'instruction `eret` qui permet de sortir du noyau. C'est la seule instruction permettant de sortir du noyau. 186 188 - `PC` ← `EPC` 187 189 - `c0_SR.EXL` ← `0` (ainsi les bits `c0_SR.UM` et `c0_SR.IE` sont à nouveau utilisés) 188 '' '''''''''''''190 '' 189 191 }}} 190 192 … … 192 194 193 195 == A2. Langage C pour la programmation système 196 194 197 195 198 … … 201 204 202 205 203 1. En assembleur, vous utilisez les sections prédéfinies `.data` et `.text` pour placer respectivement les data et le code ou alors vous pouvez créer vos propres sections avec la directive `.section` (nous avons utilisé cette possibilité pour la section `.boot`). Il est aussi possible d'imposer ou de créer des sections en langage C avec le mot clé `__attribute__`. Ce mot clé du C permet de demander certains comportements au compilateur. Il y a en a beaucoup (si cela vous intéresse vous pouvez regarder dans la [https://gcc.gnu.org/onlinedocs/gcc-3.2/gcc/Variable-Attributes.html doc de GCC sur les attributs]. En cours, nous avons vu un attribut permettant de désigner ou créer une section dans laquelle est mise la fonction concernée. Quelle était la syntaxe de cet attribut (regardez sur le slide 38). 204 {{{#!protected ------------------------------------------------------------------------------------ 205 ''''''''''''''' 206 1. En assembleur, vous utilisez les sections prédéfinies `.data` et `.text` pour placer respectivement les data et le code, mais vous pouvez créer vos propres sections avec la directive `.section` (nous avons utilisé cette possibilité pour la section `.boot`). Il est aussi possible d'imposer ou de créer des sections en langage C avec la directive `__attribute__`. Cette directive du C permet de demander certains comportements au compilateur. Il y a beaucoup d'attributs possibles (si cela vous intéresse vous pouvez regarder dans la [https://gcc.gnu.org/onlinedocs/gcc-3.2/gcc/Variable-Attributes.html doc de GCC sur les attributs]. En cours, nous avons vu un attribut permettant de désigner ou créer une section dans laquelle est mise la fonction concernée. Quelle est la syntaxe de cet attribut ? 207 {{{#!protected ------------------------------------------------------------------------------------ 208 '' 209 Cours 10 / slide 38 206 210 - `__attribute__ ((section (".start")))`\\Remarquez la syntaxe un peu curieuse avec les doubles underscore et les doubles parenthèses. 207 '' '''''''''''''208 }}} 209 1. En C, vous savez que les variables globales sont toujours initialisées, soit explicitement dans le programme lui-même, soit implicitement à la valeur `0`. Les variables globales initialisées sont placées dans la section `.data` (ou plutôt dans l'une des sections `data` : `.data`, `.sdata`, `.rodata`, etc.) et elles sont présentes dans le fichier objet (`.o`) produit pas le compilateur. En revanche, les variables globales non explicitement initialisées ne sont pas présentes dans le fichier objet. Ces dernières sont placées dans un segment de la famille `.bss`. Le fichier ldscript permet de mapper l'ensemble des segments en mémoire. Pour pouvoir initialiser à `0` les segments `bss` par programme, il nous faut connaître les adresses de début et de fin où ils sont placés en mémoire.\\ \\Le code ci-dessous est le fichier ldscript du kernel `kernel.ld` (nous avons retierles commentaires mais ils sont dans les fichiers).\\Expliquez ce que font les lignes 11, 12 et 15.211 '' 212 }}} 213 1. En C, vous savez que les variables globales sont toujours initialisées, soit explicitement dans le programme lui-même, soit implicitement à la valeur `0`. Les variables globales initialisées sont placées dans la section `.data` (ou plutôt dans l'une des sections `data` : `.data`, `.sdata`, `.rodata`, etc.) et elles sont présentes dans le fichier objet (`.o`) produit pas le compilateur. En revanche, les variables globales non explicitement initialisées ne sont pas présentes dans le fichier objet. Ces dernières sont placées dans un segment de la famille [https://www.wikiwand.com/fr/Segment_BSS `.bss`]. Le fichier ldscript permet de mapper l'ensemble des segments en mémoire. Pour pouvoir initialiser à `0` les segments `bss` par programme, il nous faut connaître les adresses de début et de fin où ils sont placés en mémoire.\\ \\Le code ci-dessous est le fichier ldscript du kernel `kernel.ld` (nous avons retiré les commentaires mais ils sont dans les fichiers).\\Expliquez ce que font les lignes 11, 12 et 15. 210 214 {{{#!java 211 215 1 SECTIONS … … 228 232 }}} 229 233 {{{#!protected ------------------------------------------------------------------------------------ 230 ''''''''''''''' 234 '' 235 Cours 10 / slide 28 231 236 - La ligne 11 contient `. = ALIGN(4)`, c'est équivalent à la directive `.align 4` de l'assembleur. 232 237 Cela permet de déplacer le pointeur de remplissage de la section de sortie courante (c'est-à-dire ici `.kdata`) sur une … … 236 241 - La ligne 15 permet de créer la variable `__bss_end` qui sera l'adresse de fin de la zone `bss` 237 242 (en fait c'est la première adresse qui suit juste `bss`. 238 '' '''''''''''''243 '' 239 244 }}} 240 245 1. Nous connaissons les adresses des registres de périphériques. Ces adresses sont déclarées dans le fichier ldscript `kernel.ld`. Ci-après, nous avons la déclaration de la variable de ldscript `__tty_regs_map`. Cette variable est aussi utilisable dans les programmes C, mais pour être utilisable par le compilateur C, il est nécessaire de lui dire quel type de variable c'est, par exemple une adresse d'entier ou une adresse de tableau d'entiers, Ou encore, une adresse de structure.\\ \\Dans le fichier `kernel.ld`: … … 255 260 À quoi servent les mots clés `extern` et `volatile` ?\\Si `NTTYS` est une macro dont la valeur est `2`, quelle est l'adresse en mémoire `__tty_regs_map[1].read` ? 256 261 {{{#!protected ------------------------------------------------------------------------------------ 257 ''''''''''''''' 262 '' 263 Cours 10 / slide 53 258 264 - `extern` : informe le compilateur que la variable définie existe ailleurs. Grâce à son type, le compilateur sait s'en servir. 259 265 - `volatile` : informe le compilateur que la variable peut changer de valeur toute seule et que donc il doit toujours accéder en mémoire à chaque fois que le programme le demande. Il ne peut donc pas optimiser les accès mémoire en utilisant les registres. 260 266 - `__tty_regs_map` est un tableau à 2 cases (puisque `NTTYS`=`2`). Chaque case est une structure de 4 entiers, donc `0x10` octets.\\`read` est le troisième champ, c'est le troisième entier de la structure, donc en `+8` par rapport au début.\\En conséquence `__tty_regs_map[1].read` est en `0xd0200018` 261 '' '''''''''''''267 '' 262 268 }}} 263 269 1. Certaines parties du noyau sont en assembleur. Il y a au moins les toutes premières instructions du code de boot (démarrage de l'ordinateur) et l'entrée dans le noyau (kentry) après l'exécution d'un syscall. Le gestionnaire de syscall est écrit en assembleur et il a besoin d'appeler une fonction écrite en langage C. Ce que fait le gestionnaire de syscall est: