Changes between Version 14 and Version 15 of Archi-1-TP10


Ignore:
Timestamp:
Dec 30, 2020, 11:19:35 AM (4 years ago)
Author:
franck
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Archi-1-TP10

    v14 v15  
    242242'''''''''''''''
    243243}}}
    244 1. Certaines parties du noyau sont en assembleur, il y au moins les toutes premières instructions du code de boot et l'entrée dans le noyau après l'exécution d'un syscall. Dans ce dernier cas, le gestionnaire de syscall écrit en assembleur a besoin d'appeler une fonction écrite en langage C. Si le gestionnaire de syscall connait l'adresse de la fonction C qu'il veut appeler et qu'il la place dans un registre, par exemple `$2`, il suffit qu'il exécuter l'instruction `jal $2`. Que doivent contenir les registres `$4` à `$7` et comment doit-être la pile?
    245 {{{#!protected ------------------------------------------------------------------------------------
    246 '''''''''''''''
    247 -
    248 '''''''''''''''
    249 }}}
    250 1. Vous avez appris à écrire des programmes assembleur, mais parfois il est plus simple, voire il est nécessaire de mélanger le code C et le code assembleur. Dans l'exemple ci-dessous, nous voyons comment la fonction `kinit()` procède pour entrer dans la fonction placée à l'adresse `__crt0` définie dans le fichier `kernel/ld`. Combien vaut cette adresse? Dans quelle section se trouve-t-elle? Quelle fonction est à cette adresses? Pourquoi doit-on écrire ce code en assembleur?
     2441. Certaines parties du noyau sont en assembleur. Il y au moins les toutes premières instructions du code de boot (démarrage de l'ordinateur) et l'entrée dans le noyau après l'exécution d'un syscall. Dans ce dernier cas, le gestionnaire de syscall écrit en assembleur a besoin d'appeler une fonction écrite en langage C. Le gestionnaire de syscall trouve l'adresse de la fonction C qu'il doit appeler puis il place cette adresse dans un registre, par exemple `$2`. Il suffit qu'il exécute l'instruction `jal $2` pour appeler la fonction. Que doivent contenir les registres `$4` à `$7` et comment doit-être la pile?
     245{{{#!protected ------------------------------------------------------------------------------------
     246'''''''''''''''
     247- C'est un appel de fonction, il faut donc respecter la convention d'appel des fonctions
     248  - Les registre `$4`à `$7` contiennent les arguments de la fonction
     249  - Le pointeur de pile doit pointer sur la case réservée pour le premier argument et les cases suivantes sont réservées
     250    arguments suivants.
     251  - Ce n'est pas rappelé ici, mais il y a **au plus** 4 arguments (entier ou pointeur) pour tous les syscalls.
     252    En conséquence, le pointeur de pile pointe au début d'une zone vide de 4 entiers.
     253'''''''''''''''
     254}}}
     2551. Vous avez appris à écrire des programmes assembleur, mais parfois il est plus simple, voire il est nécessaire de mélanger le code C et le code assembleur. Dans l'exemple ci-dessous, nous voyons comment la fonction `kinit()` procède pour entrer dans la fonction placée à l'adresse `__crt0` définie dans le fichier `kernel.ld`. Remarquez la syntaxe, ici `volatile` permet de dire au compilateur d'insérer le code tel que sans le modifier. Notez aussi l'absence de `,` entre les chaînes de caractères. Le premier argument de `__asm__` est une chaîne de caractères unique dans laquelle les instructions sont séparées par de `\n`. Il peut y avoir d'autres arguments, nous ne les verrons pas.\\Dans quelle section se trouve l'adresse `__crt0`? Combien vaut elle? Est-ce que cette valeur est imposée par le processeur MIPS comme l'adresse de boot ou d'entrée dans le kernel? Quelle fonction est à cette adresses? Pourquoi doit-on écrire ce code en assembleur?
    251256{{{#!c
    252257  9 void kinit (void)
     
    254259 11     kprintf (0, banner);
    255260 12     __asm__ volatile (          // this code allows to exit the kernel to go to user code
    256  13                          "la     $26,    __crt0         \n"     // get first address of user cod    e
     261 13                          "la     $26,    __crt0         \n"     // get first address of user code
    257262 14                          "mtc0   $26,    $14            \n"     // put it in c0_EPC
    258263 15                          "li     $26,    0b00010010     \n"     // next status [UM,0,ERL,EXL,IE]     
     
    264269{{{#!protected ------------------------------------------------------------------------------------
    265270'''''''''''''''
    266 -
     271- L'adresse `__crt0` est la première adresse de la section `text` dans laquelle se trouve le code de l'application.
     272- Elle vaut `0X7F400000`.
     273- Cette adresse n'est pas imposée par le MIPS. C'est le choix des architectes de SoC. La seule condition est que cette adresse soit
     274  dans la partie accessible en mode user.
     275- A cette adresse, on place la fonction `__start()`.
     276- On est obligé d'écrire ce code en assembleur parce que la manière de changer de mode (de `kernel` à `user`) est propre à chaque processeur. Il n'y a aucun moyen de le faire en C.
    267277'''''''''''''''
    268278}}}