Changes between Version 15 and Version 16 of Archi-1-TD9


Ignore:
Timestamp:
Nov 18, 2022, 10:14:49 AM (3 years ago)
Author:
franck
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Archi-1-TD9

    v15 v16  
    169169''
    170170* Ce qu'il faut comprendre, c'est que les comportements du `C` et de l'assembleur sont inversés vis-à-vis des labels. Dans un fichier `.c`, quand on définit un label (une fonction ou variable), ce label est par défaut `extern`, c'est-à-dire qu'il est utilisable dans un autre fichier `.c`. Si on veut que le label ne soit utilisable que dans le fichier dans lequel il est défini, il faut utiliser le mot clé `static` lors de sa déclaration. En assembleur, c'est l'inverse, les labels sont par défaut `static`, c'est-à-dire utilisable uniquement dans le fichier où ils sont définis. Si on veut qu'ils soient utilisables dans les autres fichiers, il faut le dire avec la directive `.globl`.
    171 * `globl` signifie `glob`al `l`abel. Cette directive permet de dire que le `label` est visible en dehors de son fichier de définition. Ainsi il est utilisable dans les autres fichiers assembleur ou les autres fichier C du programme.
     171* `globl` signifie `glob`al `l`abel. Cette directive permet de dire que le `label` est visible en dehors de son fichier de définition. Ainsi il est utilisable dans les autres fichiers assembleur ou les autres fichiers C du programme.
    172172''
    173173}}}
     
    195195{{{#!protected ------------------------------------------------------------------------------------
    196196''
    197 * On parle ici du pointeur de pile pour le `kernel`, on doit mettre le pointeur de pile dans la section des données du kernel. Ici, il n'y en a qu'une c'est `.kdata`. La pile est mise en haut de cette de cette section aux adresses les plus grandes. Les adresses du bas de la section sont occupées par les données globales du kernel.
    198 * La pile va être initialisée juste à la première adresse au-delà de la zone kdata donc\\`__kdata_end = 0x80020000` + `0x003E0000` = `0x80400000`\\Oui, on initialise le pointeur de pile a une adresse qui est en dehors du segment! Ce n'est pas un problème parce que le compilateur C n'écrira jamais à cette adresse, car elle n'est pas dans le contexte de la fonction C. La première chose qu'il fera c'est décrémenter le pointeur de pile pour pour allouer le contexte de la fonction.
     197* On parle ici du pointeur de pile pour le `kernel`, on doit mettre le pointeur de pile dans la section des données du kernel. Ici, il n'y en a qu'une c'est `.kdata`. La pile est mise en haut de cette section aux adresses les plus grandes. Les adresses du bas de la section sont occupées par les données globales du kernel.
     198* La pile va être initialisée juste à la première adresse au-delà de la zone kdata donc\\`__kdata_end = 0x80020000` + `0x003E0000` = `0x80400000`\\Oui, on initialise le pointeur de pile a une adresse qui est en dehors du segment! Ce n'est pas un problème parce que le compilateur C n'écrira jamais à cette adresse, car elle n'est pas dans le contexte de la fonction C. La première chose qu'il fera, c'est décrémenter le pointeur de pile pour allouer le contexte de la fonction.
    199199* En effet, la première chose que fait une fonction, c'est décrémenter le pointeur de pile pour écrire `$31`, etc. Il faut donc que le pointeur ait été défini avant d'entrer dans la fonction.
    200200{{{#!asm
     
    284284Nous allons systématiquement utiliser des Makefiles pour la compilation du code, mais aussi pour lancer le simulateur du prototype **almo1**. Pour cette première séance, les Makefiles ne permettent pas de faire des recompilations partielles de fichiers. Les Makefiles sont utilisés pour agréger toutes les actions que nous voulons faire sur les fichiers, c'est-à-dire : compiler, exécuter avec ou sans trace, nettoyer le répertoire. Nous avons recopié partiellement le premier Makefile pour montrer sa forme et poser quelques questions, auxquels vous savez certainement répondre.
    285285
    286 La syntaxe des `Makefile`s peut-être très complexe (c'est un vieux langage), ici nous ne verrons qu'une petite partie. Notez que le Makefile `voit` les variables du `shell` comme s'il les avait définies lui même.
     286La syntaxe des `Makefile`s peut-être très complexe (c'est un vieux langage), ici nous ne verrons qu'une petite partie. Notez que le Makefile `voit` les variables du `shell` comme s'il les avait définies lui-même.
    287287{{{#!make
    288288# Tools and parameters definitions
     
    332332* Le compilateur C peut avoir beaucoup de paramètres. Définir une variable `CFLAGS` permet de les déclarer une fois au début et d'utiliser cette variable plusieurs fois dans le `Makefile`. Si on veut changer un argument, il suffit de le faire une seule fois. Ce genre de choses est nécessaire si on veut faire des `Makefile`s facile à lire et à faire évoluer.
    333333* La variable `CFLAGS` est utilisée par `gcc`, il y a ici toutes les options indispensables pour compiler mais il en existe beaucoup, ce qui fait des tonnes de combinaison d'options !
    334 * `-DNTTYS=$(NTTY)` permet de définir et donner une valeur à une macro (ici définition `NTTYS` avec la valeur `$(NNTY)` comme le fait un `#define` dans un fichier C. Cette commande éviter donc d'ouvrir les codes pour les changer.
     334* `-DNTTYS=$(NTTY)` permet de définir et donner une valeur à une macro (ici définition `NTTYS` avec la valeur `$(NNTY)` comme le fait un `#define` dans un fichier C. Cette commande évite donc d'ouvrir les codes pour les changer.
    335335''
    336336}}}
     
    346346{{{#!protected ------------------------------------------------------------------------------------
    347347''
    348 * `@` permet de ne pas afficher la commande avant son exécution. On peut rendre ce comportement systématique en ajoutant la règle `.SILENT:` n'importe où dans le fichier.
    349 * `-`  permet de ne pas stopper l'exécution des commandes même si elles rendent une erreur, c'est-à-dire une valeur de sortie différente de 0.
     348* `@` permets de ne pas afficher la commande avant son exécution. On peut rendre ce comportement systématique en ajoutant la règle `.SILENT:` n'importe où dans le fichier.
     349* `-`  permets de ne pas stopper l'exécution des commandes même si elles rendent une erreur, c'est-à-dire une valeur de sortie différente de 0.
    350350''
    351351}}}
     
    377377''
    378378* Le cours 9 n'en parle pas, mais dans le code vous trouverez cette directive un peu partout. Il y a deux usages.
    379  1. Déclarer `static` une variable globale ou une fonction en faisant précéder leur définition du mot clé `static` permet de limiter la visibilité de cette variable ou de cette fonction au seul fichier de déclaration. Notez que par défaut les variables et les fonctions du C ne sont pas `static`, il faut le demander explicitement. C'est exactement l'inverse en assembleur où tout label est implicitement  `static` ; il faut demander avec la directive `.globl` de le rendre visible.
     379 1. Déclarer `static` une variable globale ou une fonction en faisant précéder leur définition du mot clé `static` permets de limiter la visibilité de cette variable ou de cette fonction au seul fichier de déclaration. Notez que par défaut les variables et les fonctions du C ne sont pas `static`, il faut le demander explicitement. C'est exactement l'inverse en assembleur où tout label est implicitement  `static` ; il faut demander avec la directive `.globl` de le rendre visible.
    380380 1. Déclarer `static` une variable locale permet de la rendre persistante, c'est-à-dire qu'elle conserve sa valeur entre deux appels. Cette variable locale n'est pas dans le contexte de la fonction (c'est-à-dire qu'elle n'est pas dans la pile parce que le contexte est libéré en sortie de fonction). Une variable locale `static` est en fait allouée comme une variable globale mais son usage est limité à la seule fonction où elle est définie.
    381381''
     
    385385''
    386386* Ça n'ont plus ce n'est pas dit dans le cours mais c'est sensé être connu, sinon c'est qu'il y a des choses à apprendre. Notez que la directive externe est implicite en C et qu'on peut donc ne pas l'écrire. On la met pour la lisibilité du code.
    387 * Les déclarations `extern` permettent d'informer que le compilateur qu'une variable ou qu'une fonction existe et est définie ailleurs. Le compilateur connaît ainsi le type de la variable ou du prototype des fonctions, il sait donc comment les utiliser. En C, par défaut, les variables et les fonctions doivent être déclarées / leur existence et type doit être connus avant leur utilisation.
     387* Les déclarations `extern` permettent d'informer que le compilateur qu'une variable ou qu'une fonction existe et est définie ailleurs. Le compilateur connaît ainsi le type de la variable ou du prototype des fonctions, il sait donc comment les utiliser. En C, par défaut, les variables et les fonctions doivent être déclarées / leur existence et leur type doivent être connus avant leur utilisation.
    388388* Il n'y a pas de déclaration `extern` en assembleur parce que ce n'est pas un langage typé. Pour l'assembleur, un label c'est juste une adresse donc un nombre.
    389389''