Changes between Version 68 and Version 69 of Archi-1-TP9


Ignore:
Timestamp:
Dec 4, 2020, 9:26:00 AM (4 years ago)
Author:
franck
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Archi-1-TP9

    v68 v69  
    282282}}}
    2832831. Supposons que la structure `tty_s` et le tableau de registres de `TTY` soient définis comme suit. Écrivez une fonction C `int getchar(void)` bloquante qui attend un caractère tapé au clavier sur le `TTY0`. Nous vous rappelons qu'il faut attendre que le registre `TTY_STATUS` soit différent de 0 avant de lire `TTY_READ`.
    284 
    285284{{{#!c
    286285struct tty_s {
     
    303302'''''''''''''''
    304303}}}
    305 
    306 
    307 == A3. Chaîne de compilation
     3041. Savez-vous à quoi sert le mot clé `volatile` ? Nous n'en avons pas parlé en cours, mais c'est nécessaire pour les adresses des registres de périphérique, une idée ... ?
     305{{{#!protected ------------------------------------------------------------------------------------
     306'''''''''''''''
     307* `volatile` permet de dire à `gcc` que la variable en mémoire peut changer à tout moment, elle est volatile. Ainsi quand le programme demande de lire une variable `volatile` le compilateur doit toujours aller la lire en mémoire. Il ne doit jamais chercher à optimiser en utilisant un registre afin de réduire le nombre de lecture mémoire (load). De même, quand le programme écrit dans une variable `volatile`, cela doit toujours provoquer une écriture dans la mémoire (store).
     308* Ainsi, les registres de périphériques doivent toujours être directement lus ou écrits à chaque fois que le programme le demande, parce que c'est justement ces lectures et ces écritures qui commandent le périphérique.
     309'''''''''''''''
     310}}}
     311
     312
     313
     314== A3. Compilation
     315
    308316
    309317
    310318Pour obtenir le programme exécutable nous allons utiliser :
    311319* `gcc -o file.o -c file.c`
    312   - Appel du compilateur avec l'option `-c` qui demande à gcc de faire le préprocessing puis la compilation c pour produire le fichier objet `file.o`
    313 * `ld -o bin.x -Tldscript files.o ...`
     320  - Appel du compilateur avec l'option `-c` qui demande à `gcc` de faire le préprocessing puis la compilation c pour produire le fichier objet `file.o`
     321* `ld -o bin.x -Tkernel.ld files.o ...`
    314322  - Appel de l'éditeur de lien pour produire l'exécutable `bin.x` en assemblant tous les fichiers objets `.o`, en les plaçant dans l'espace d'adressage et résolvant les liens entre eux (quand un `.o` utilise une fonction ou une variable définie dans un autre `.o`).
    315 $ objdump
    316 1. Le fichier « ldscript » décrit l'espace d'adressage et la manière de remplir les sections dans le programme exectutable. Quelle étape dans la chaîne de compilation a besoin de cette description ?
    317  Les variables déclarées externes ne sont évidemment pas mise dans la section `.data` du fichier objet en sortie et les appel au fonction sont codés par des `jal ?` puisque le code des fonctions n'est pas là. Ce sera ré
     323* `objdump -D file.o > file.o.s` ou `objdump -D bin.x > bin.x.s`
     324  - Appel du désassembleur prend les fichiers binaires (`.o` ou `.x`) pour retrouver le code produit par le compilateur à des fins de debug ou de curiosité.
     325
     326**Questions**
     3271. Le fichier `kernel.ld` décrit l'espace d'adressage et la manière de remplir les sections dans le programme exécutable.
     328{{{#!c
     329__tty_regs_map   = 0xd0200000 ;
     330__boot_origin    = 0xbfc00000 ;
     331__boot_length    = 0x00001000 ;
     332__ktext_origin   = 0x80000000 ;
     333__ktext_length   = 0x00020000 ;
     334[... question 1 ...]
     335__kdata_end      = __kdata_origin + __kdata_length ;
     336
     337MEMORY {
     338    boot_region  : ORIGIN = __boot_origin,  LENGTH = __boot_length
     339    ktext_region : ORIGIN = __ktext_origin, LENGTH = __ktext_length
     340[... question 2 ...]
     341}
     342
     343SECTIONS {
     344    .boot : {
     345        *(.boot)   
     346    } > boot_region
     347[... question 2 ...]
     348    .kdata : {
     349        *(.*data*)     
     350    } > kdata_region
     351}
     352}}}
     3531.  ?
     354{{{#!protected ------------------------------------------------------------------------------------
     355'''''''''''''''
     356*
     357'''''''''''''''
     358}}}
     359 - Le fichier commence par la déclaration des variables donnant des informations sur les adresses et les tailles des régions de mémoire. Ces symboles n'ont pas de type et ils sont visibles de tous les programmes c, il faut juste leur donner un type pour le compilateur puisse les exploiter, c'est ce que nous avons fait pour `extern volatile struct tty_s __tty_regs_map[NTTYS]`
     360 - Le fichier contient ensuite la déclaration des régions qui vont être remplies par les sections trouvées dans les fichiers objets.
     361 - Enfin le fichier contient comment sont remplies les régions avec les sections
     362 
     363 Les variables déclarées externes ne sont évidemment pas mises dans la section `.data` du fichier objet en sortie et les appels aux fonctions sont codés par des `jal ?` puisque le code des fonctions n'est pas là. Ce sera ré
    318364
    319365