Cours de l’Architecture des Ordinateurs - PDF
Document Details
Uploaded by LeadingMossAgate9366
2023
Said LAKHAL
Tags
Summary
This document appears to be a course outline or syllabus for a computer architecture course, focusing on computer organization, Von Neumann architecture, and MIPS assembly language. The document details the topics to be covered.
Full Transcript
Cours de l’Architecture des Ordinateurs Filière : Sciences Mathématique et Informatique (SMI) Semestre : S4 Professeur : Said LAKHAL Année Universitaire : 2023/2024 1 Table des matières........................................................
Cours de l’Architecture des Ordinateurs Filière : Sciences Mathématique et Informatique (SMI) Semestre : S4 Professeur : Said LAKHAL Année Universitaire : 2023/2024 1 Table des matières........................................................................................................................................................... 1 Chapitre 1 : Introduction à l’architecture des ordinateurs......................................................... 4 Historique..................................................................................................................................... 4 Architecture de Von Neumann................................................................................................... 7 Principaux Composants externes d’un ordinateur................................................................... 8 Unité Centrale.............................................................................................................................. 9 Chapitre 2 : Unités fonctionnelles................................................................................................ 11 Introduction aux unités fonctionnelles :.................................................................................. 11 Mémoire :................................................................................................................................... 12 Unités d'entrée/sortie :.............................................................................................................. 12 Bus système :.............................................................................................................................. 12 Unité de contrôle :..................................................................................................................... 13 Architecture de von Neumann vs Harvard :........................................................................... 14 Pipeline d'instructions :............................................................................................................. 15 Chapitre 3 : Introduction à la programmation en assembleur.................................................. 17 Interruptions.............................................................................................................................. 17 Code Assembleur....................................................................................................................... 18 Chapitre 4 : Architecture MIPS................................................................................................... 22 Aperçu de l'architecture............................................................................................................ 22 Types/Tailles de données........................................................................................................... 23 Mémoire...................................................................................................................................... 23 Disposition de la mémoire......................................................................................................... 24 Registers du processeur............................................................................................................. 25 Registres réservés...................................................................................................................... 26 Registres Divers......................................................................................................................... 27 Configuration du cœur CPU / FPU.......................................................................................... 27 Déclaration et types de données............................................................................................... 28 2 Structure générale d’un programme....................................................................................... 29 Opérations Arithmétiques......................................................................................................... 31 Entrées Sorties........................................................................................................................... 31 Chapitre 6 : Instruction de branchement.................................................................................... 37 Mouvement des données du registre des nombres entiers/à virgule flottante.......................... 39 Instructions de conversion nombre entier/virgule flottante...................................................... 40 Chapitre 7 : La notion de la pile................................................................................................... 42 Empiler........................................................................................................................................... 42 Empiler........................................................................................................................................... 43 Dépiler............................................................................................................................................ 43 Chapitre 8 : Les fonctions............................................................................................................. 47 Introduction................................................................................................................................... 47 Conventions d’appel MIPS........................................................................................................... 47 Format de procédure/fonction...................................................................................................... 47 Conventions des appelants............................................................................................................ 48 3 Chapitre 1 : Introduction à l’architecture des ordinateurs Historique On commence d'abord par la définition d'un ordinateur, qui représente une machine capable de traiter l'information automatiquement. Plusieurs générations ont succédé afin d'aboutir aux ordinateurs contemporains. À cet égard, on peut distinguer quatre importantes générations : 1ère génération (1946-1957) : Connue sous le nom d'Electronic Numerical Integrator and Calculator (ENIAC), il s'agit d’une machine pesante presque 30 tonnes, contenant 1800 tubes. Elle est basée sur la technologie à lampes, relais et résistances, capable d'exécuter 40 000 opérations par seconde avec une fiabilité faible et une possibilité de programmation par cartes perforées (figure 1). 4 Figure 1 : 1ère génération des ordinateurs 2ème génération (1958- 1964) : Avec l'apparition de cette génération, le degré de fiabilité a été augmenté grâce à l'introduction des fameux transistors, qui ont bouleversé la structure et les performances des calculateurs. Ainsi, le nombre d'opérations exécutées a été porté à 200 000 opérations par seconde. Cette génération a également été marquée par l'émergence de nouveaux langages de programmation, à savoir : COBOL, FORTRAN, LISP (Figure2). 3ème génération (1965- 1971) : Cette génération a été caractérisée par l'assemblage des composants électroniques dans un circuit intégré afin de réaliser des tâches spécifiques. Le fameux processeur a atteint le sommet de ces circuits intégrés, réalisé pour la première fois en 1971 par la société INTEL (Figure 3), avec une vitesse de 106 opérations par seconde. Cette génération a également été marquée par l'émergence des premiers systèmes d'exploitation, à savoir : UNIX, Pascal, Basic et CISC. Figure 2 : 2ème génération des ordinateurs 5 Figure 3 : 3ème génération des ordinateurs et le processeur Intel 4ème génération (1972- 1977) : Le nombre d'opérations exécutées par seconde a été augmenté à 10^7, avec une possibilité d'échange d'informations entre les machines et la répartition de tâches entre elles (Figure 4). Cette technologie a été nommée : technologie LSI (Large Scale Integration), impliquant l'intégration de centaines de milliers de transistors sur une seule puce, permettant ainsi, la réalisation de fonctions complexes. Figure 4 : 4ème génération des ordinateurs et la technologie LSI 5ème génération (1978) : Connue par l'émergence de la technologie multimédia et la possibilité de traiter tous types d'informations, y compris le texte, le son et l'image (figure 5). Les concepts de distribution et de parallélisme ont pris un sens étendu avec la naissance de l'architecture Client-Serveur, du parallélisme massif et des systèmes distribués interactifs. En bref, cette technologie a été désignée par l'acronyme VLSI/WSI (Very Large Scale Integration/Wafer Scale Integration). 6 Figure 5 : 5ème génération des ordinateurs et la technologie VLSI/WSI Architecture de Von Neumann Avec Alan Turing, von Neumann peut être considéré comme le père des ordinateurs et de l'informatique moderne. Car, l'architecture de la majorité des ordinateurs est dite de type von Neumann. Ce scientifique a contribué en plusieurs disciplines scientifiques, y compris : la mécanique quantique, l’analyse fonctionnelle, la théorie des ensembles. Mais son apport dans la structuration fonctionnelle des premiers ordinateurs a été distingué. Il a conçu l’organisation et le fonctionnement des composants internes d’un ordinateurs. Cette architecture utilise une unité de traitement (CPU) contenant deux unités : unité de contrôle et l’unité arithmétique et logique, ainsi qu’un support de stockage mémoire constituée de trois unités : ROM et RAM, pour loger les instructions et les données, et les registres pour le stockage temporaire des données ou des instructions, transitées via des bus entre différentes unités (figure 6). 7 Figure 6 : Architecture de Von Neumann Principaux Composants externes d’un ordinateur L'ordinateur communique avec son environnement extérieur via des périphériques externes, directement accessibles par l'utilisateur et connectés à l'unité centrale par le biais de ports (Figure 7). On distingue deux familles de périphériques renommées : les périphériques d'entrée et les périphériques de sortie. La première catégorie assure l'envoi d'informations de l'utilisateur vers l'unité centrale, tandis que la deuxième catégorie assure le rôle inverse 8 Figure 7 : Périphériques d’un ordinateur Unité Centrale L’unité centrale est constituée de plusieurs composants, dont chacun a une fonctionnalité précise : Processeur (CPU) : C'est le cerveau de l'ordinateur, il exécute toutes les instructions. Mémoire vive (RAM) : Assurant le stockage temporaire de données. Une fois l’ordinateur est éteint toutes les données stockées sont perdues. Carte mère : Il s’agit d’une carte électronique, et comme son nom l’indique, elle représente le composant de référence pour tous les composants internes et tous les périphériques. Carte graphique (GPU) : Servant à encoder et décoder les données graphiques. Disque dur (HDD) ou Disque SSD : C’est une mémoire de stockage à grande capacité et à long terme. Ainsi, son contenu reste conservé même en absence d’une alimentation électrique. Le mécanisme de HDD est mécanique, alors que celui de SSD est électrique ; ce qui rend ce dernier plus rapide en termes d’accès aux données. Alimentation : C’est la source qui assure la disponibilité de l’énergie aux différents composants. 9 Cartes d'extension : y compris la carte son, spécialisée dans le traitement des données audio ; et la carte réseaux, permettant de connecter l’ordinateur aux autres ordinateurs. Ventilateurs et système de refroidissement : Ce système conserve une température modérée au sein de l’unité centrale, afin d’éviter tout endommagement des composants grâce à l’augmentation de la température. Figure 8 : Composants internes d’un ordinateur 10 Chapitre 2 : Unités fonctionnelles Introduction aux unités fonctionnelles : Unités fonctionnelles. Définition Les unités fonctionnelles d'un ordinateur désignent les différentes composantes matérielles collaborant ensemble, afin d’assurer le bon fonctionnement de l'ordinateur. Ainsi, il est primordial de bien comprendre le fonctionnement de chaque unité, et sa relation avec les autres afin d’avoir une idée générale sur le fonctionnement de l’ordinateur. Unité centrale de traitement (UCP) : UCP désigne l’unité de contrôle et de traitement. Comme son nom l’indique elle est responsable de toutes les opérations arithmétiques et logiques, et aussi de toutes les instructions de contrôle. Par conséquent, elle est constituée de deux unités : Unité Arithmétique et Logique (UAL) et l’Unité de Contrôle (UC). Figure 9: Schéma de l’UCP Exécution d’un programme par le processeur L’exécution d’un programme par le processeur stocké sur la RAM suit les étapes suivantes : 11 Récupération L'unité de contrôle charge l'instruction suivante depuis la mémoire principale (RAM) vers le registre d'instruction. L'adresse de l'instruction à exécuter est fournie par le compteur d'instruction. Mémoire : On peut distinguer entre deux types de mémoires : RAM (Random Access Memory) et ROM (Read Only Memory). La première est utilisée pour le stockage temporaire de données, que le processeur de l'ordinateur peut rapidement accéder et modifier. Alors que la deuxième généralement utilisée pour stocker des données qui ne changent pas fréquemment, voire pas du tout, pendant la durée de vie d'un appareil. Ces données peuvent inclure le micrologiciel du système d'exploitation, le BIOS (Basic Input/Output System) d'un ordinateur, ou d'autres types de logiciels essentiels au fonctionnement de l'appareil. Unités d'entrée/sortie : Périphériques d'Entrée : Les périphériques d'entrée sont utilisés pour introduire des données ou des commandes dans l'ordinateur. Ils permettent à l'utilisateur de communiquer avec l'ordinateur en fournissant des informations ou des instructions. Exemples de périphériques d'entrée : clavier, souris, scanner, webcam, microphone, etc. Ces périphériques traduisent les actions physiques ou les données analogiques en signaux numériques compréhensibles par l'ordinateur. Périphériques de Sortie : Les périphériques de sortie affichent les résultats du traitement effectué par l'ordinateur. Ils permettent à l'ordinateur de communiquer des informations à l'utilisateur. Exemples de périphériques de sortie : écran (moniteur), imprimante, haut-parleurs, etc. Ces périphériques traduisent les données numériques en formes perceptibles par les sens humains, comme des images, des sons, ou du texte. Bus système : Définition Un bus système, également appelé bus principal, est un ensemble de lignes de communication qui facilitent le transfert de données entre différents composants d'un système informatique. Ces 12 composants peuvent inclure le processeur, la mémoire, les périphériques d'entrée/sortie, et d'autres unités fonctionnelles. Ainsi, on peut distinguer entre trois types de bus. Bus de données Le bus de données est une composante essentielle de l'architecture informatique qui facilite le transfert de données à l'intérieur d'un système informatique. Il est utilisé pour acheminer les données entre les différents composants du système, tels que le processeur, la mémoire et les périphériques. Bus d’adresse Le bus d'adresse est une composante clé de l'architecture informatique, utilisée pour spécifier l'emplacement mémoire auquel un processeur doit accéder. Il travaille en tandem avec le bus de données et d'autres signaux de contrôle pour coordonner le transfert d'informations à l'intérieur d'un système informatique. Bus de contrôle Le bus de contrôle, également appelé bus de contrôle système, est une composante essentielle de l'architecture d'un système informatique. Ce bus est utilisé pour transporter des signaux de contrôle qui dirigent et coordonnent les opérations des différents composants du système, tels que le processeur, la mémoire et les périphériques. Unité de contrôle : L'unité de commande (UC) ou unité de contrôle est une composante centrale d'un processeur dans un système informatique. son rôle est l'exécution des instructions du programme. Décodeur d'instructions : l'unité de commande commence par lire l'instruction suivante à exécuter depuis la mémoire, souvent depuis une adresse spécifiée par le compteur de programme (program counter). Cette instruction est ensuite décodée pour comprendre quelle opération doit être effectuée. Séquencement des opérations : L'unité de commande est responsable du séquencement des opérations. Elle contrôle l'ordre dans lequel les différentes étapes de l'instruction doivent être exécutées. Cela peut inclure des opérations telles que la lecture de données depuis la mémoire, la réalisation d'opérations arithmétiques ou logiques, et la sauvegarde des résultats. Contrôle des registres : L'unité de commande gère l'accès aux registres du processeur, qui sont des emplacements de stockage temporaires utilisés pour manipuler les données pendant l'exécution des instructions. Elle spécifie quels registres doivent être lus ou écrits lors de chaque étape de l'instruction. Coordination avec l'unité arithmétique et logique (UAL) : L'unité de commande travaille en tandem avec l'unité arithmétique et logique (UAL), qui effectue les opérations arithmétiques et logiques réelles spécifiées par les instructions. L'UC 13 séquence ces opérations et s'assure que les données nécessaires sont correctement acheminées vers l'UAL. Gestion du flux de contrôle : L'unité de commande gère le flux de contrôle du programme. Cela comprend la gestion des sauts (branches) conditionnels et inconditionnels, ainsi que l'exécution séquentielle des instructions. Gestion des interruptions : L'unité de commande peut également être responsable de la gestion des interruptions. Les interruptions sont des signaux provenant de périphériques ou d'autres parties du système, indiquant qu'une attention immédiate est requise. Gestion des erreurs : En cas d'erreur ou d'exception, l'unité de commande peut prendre des mesures spécifiques, comme l'arrêt de l'exécution du programme ou la gestion de l'erreur conformément aux mécanismes prévus par le système. Architecture de von Neumann vs Harvard : Il existe plusieurs architectures fondamentales d'ordinateurs, mais deux des plus couramment utilisées sont l'architecture de type CISC (Complex Instruction Set Computing) et l'architecture de type RISC (Reduced Instruction Set Computing). Voici quelques-unes des principales différences entre ces deux architectures : Ensemble d'instructions : CISC : Les processeurs CISC ont un ensemble d'instructions complexe avec un grand nombre d'instructions, certaines d'entre elles étant très complexes. Chaque instruction peut effectuer plusieurs opérations. RISC : Les processeurs RISC ont un ensemble d'instructions réduit et généralement simple. Chaque instruction effectue une seule opération de base. Longueur des instructions : CISC : Les instructions dans une architecture CISC peuvent varier en longueur, certaines étant très longues et complexes. RISC : Les instructions dans une architecture RISC sont généralement de longueur fixe, ce qui facilite le décodage et l'exécution rapide. Complexité de l'unité de contrôle : CISC : Les processeurs CISC ont généralement une unité de contrôle plus complexe, capable de décoder et d'exécuter des instructions complexes. RISC : Les processeurs RISC ont une unité de contrôle simplifiée, car chaque instruction est simple et peut être exécutée en un cycle d'horloge. 14 Débit d'instructions : CISC : Les processeurs CISC ont tendance à avoir un débit d'instructions plus bas par cycle d'horloge en raison de la complexité des instructions. RISC : Les processeurs RISC visent à avoir un débit d'instructions plus élevé par cycle d'horloge, car les instructions sont plus simples et peuvent être exécutées plus rapidement. Optimisation matérielle : CISC : Les processeurs CISC peuvent utiliser des techniques d'optimisation matérielle pour accélérer l'exécution des instructions complexes. RISC : Les processeurs RISC dépendent souvent de l'optimisation logicielle plutôt que de l'optimisation matérielle pour améliorer les performances. Utilisation de la mémoire : CISC : Les instructions CISC peuvent impliquer des accès mémoire complexes, ce qui peut rendre l'utilisation de la mémoire moins efficace. RISC : Les architectures RISC privilégient souvent l'accès à des registres plutôt que des accès mémoire complexes, ce qui peut améliorer l'efficacité. Efficacité énergétique : CISC : En raison de la complexité des instructions, les processeurs CISC peuvent consommer plus d'énergie par instruction. RISC : Les processeurs RISC visent à être plus économes en énergie en exécutant des instructions simples et en consommant moins d'énergie par instruction. Pipeline d'instructions : Le pipeline d'instructions est une technique de conception utilisée dans les architectures de processeurs pour améliorer l'efficacité et l'utilisation des ressources. Cela implique la subdivision du processus d'exécution des instructions en plusieurs étapes distinctes, et chaque étape est effectuée par une unité spécialisée. Voici comment fonctionne généralement un pipeline d'instructions : 1. Fetch (Récupération) : La première étape consiste à récupérer l'instruction suivante depuis la mémoire. Cela est généralement effectué par l'unité de récupération d'instructions (IFU). L'instruction est extraite de la mémoire et placée dans le registre d'instruction. 2. Decode (Décodage) : L'instruction est ensuite décodée pour comprendre quelle opération doit être effectuée. Cette étape est effectuée par l'unité de décodage d'instructions (IDU). Les champs de l'instruction sont analysés pour déterminer l'opération à effectuer et les registres impliqués. 15 3. Execute (Exécution) : L'instruction est exécutée, généralement par l'unité d'exécution d'instructions (EXU). Cela peut inclure des opérations arithmétiques, logiques, de comparaison, etc. 4. Memory Access (Accès à la mémoire) : Si l'instruction nécessite un accès à la mémoire, cette étape est utilisée pour lire ou écrire des données en mémoire. L'unité d'accès à la mémoire (MAU) gère cette opération. 5. Write Back (Écriture) : Les résultats de l'instruction sont écrits dans les registres appropriés. Cela peut être réalisé par l'unité d'écriture (WU). Les résultats sont prêts à être utilisés par les instructions suivantes. Chaque étape du pipeline d'instructions est gérée par une unité spécialisée, ce qui permet à plusieurs instructions d'être traitées simultanément. Tant qu'une instruction ne dépend pas des résultats d'une instruction précédente, elle peut entrer dans le pipeline et progresser à travers les différentes étapes. 16 Chapitre 3 : Introduction à la programmation en assembleur Définition Un langage d'assemblage ou langage assembleur est, en programmation informatique, le langage de plus bas niveau qui représente le langage machine sous une forme lisible par un humain. Les combinaisons de bits du langage machine sont représentées par des symboles dits « mnémoniques », c'est-à-dire faciles à retenir. Le programme assembleur convertit ces mnémoniques en langage machine, ainsi que les valeurs (écrites en décimal) en binaire et les libellés d'emplacements en adresses, en vue de créer par exemple un fichier objet ou un fichier exécutable. Interruptions Définition Elle se produise, quand un événement arrive ; pour arrêter l’exécution normale d’un programme, et donner lieu à l’exécution d’un autre programme. Exemple Déplacement de la souris 1.2 Types d’interruptions Selon leurs provenances, on peut distinguer entre trois types d’interruptions : 1) Interruptions internes sont soulevées depuis le processeur, à cause d'une erreur ou d'une instruction d'interruption. 2) Interruptions externes proviennent de l'extérieur du processeur : 3) Interruptions logicielles, sont générées par l'instruction d'interruption. Exemples d’interruptions externes : Souris, Clavier, Timer, Lecteurs CD et DVC, carte son….. 1.3 Gestionnaire d’interruption 17 Une fois l’interruption est produite, le contrôle sera passé au gestionnaire d’interruption pour s’en occuper. Tel que à chaque interruption est associé un nombre entier, qui correspond à son tour à un code à exécuter. Au début de la RAM réside un tableau à deux colonnes, contenant le numéro de l’interruption dans la 1ère colonne et le code équivalent dans la 2ème colonne. Le gestionnaire d’interruptions assure la sauvegarde de l’état du programme encours, l’exécution du code correspondant à l’interruption, et la poursuite d’exécution du programme normal une fois le code interruption est terminé. On signale que l’exécution du code interruption est effectuée de la même façon que le programme normal, à savoir, le déroulement des instructions l’une après l’autres, l’enregistrement de l’adresse de l’instruction encours au niveau du compteur ordinal, et la sauvegarde es résultats si nécessaire sur la RAM. Code Assembleur Chaque instruction a son propre code appelé code opération ou opcode. Ce code se présente au début de la mnémonique. Parfois, la mnémonique pourra contenir des constantes ou des adresses. Exemple Le code hexadécimal de la mnémonique, qui demande l’ajout des valeurs des 2 registres EAX et EBX et de stocker le résultat dans EAX est : 03 C3 2.1 Forme générale d’une mnémonique : Opération opérandes Exemple Add eax, ebx : additionner le contenu du eax à celui de ebx, et stocker le résultat sur eax. L’assembleur fait le codage de cette mnémonique pour avoir le code hexadécimal mentionné précédemment : 03 C3 Définition L’assembleur est un programme qui lit un texte avec des mnémoniques assembleur et les convertit en code machine. Le passage d’une mnémonique à un code est très simple, car il se base sur un tableau des correspondances entre les mnémoniques et les codes équivalents. Remarque Le langage assembleur est un langage à bas niveau, car il est très proche du langage machine. Alors que, les langages à haut niveau comme C, Java.., sont des langages de haut niveau, grâce aux 18 traitements préliminaires nécessaires à effectuer sur le code source, avant d’arriver au langage machine. 2.2 Opérandes d'Instruction Le nombre d’opérandes d’une mnémonique varie entre 0 et 3. Les opérandes peuvent avoir les types suivants : 1) Registre : Ces opérandes font directement référence au contenu des registres du processeur. 2) Mémoire : Ils font référence aux données en mémoire. L'adresse de la donnée peut être une constante codée dans l'instruction ou calculée en utilisant les valeurs des registres. Les adresses sont toujours des déplacements relatifs au début d'un segment. 3) Immédiat : Ce sont des valeurs fixes qui sont listées dans l'instruction elle-même. Elles sont stockées dans l'instruction (dans le segment de code), pas dans le segment de données. 4) Implicite : Ces opérandes ne sont pas entrés explicitement. Par exemple, l'instruction d'incrémentation ajoute un à un registre ou à la mémoire. Le un est implicite 2.3 Instructions de base 1) MOV mov eax, 3 ; stocke 3 dans le registre EAX (opérande immédiat) mov bx, ax ; stocke la valeur de AX dans le registre BX ( 2 opérandes registres) 2) ADD add eax, 4 ; eax = eax + 4 (opérande immédiat) add al, ah ; al = al + ah ( 2 opérandes registres) 3) SUB sub bx, 10 ; bx = bx - 10 sub ebx, edi ; ebx = ebx – edi 19 4) INC et DEC inc ecx ; ecx++ (opération a un seul opérande) dec dl ; dl-- (opération a un seul opérande) 2.3 Directives Une directive est un indicateur destiné à l'assembleur, pas au processeur. Elles sont généralement utilisées pour demander à l'assembleur de faire quelque chose ou pour l'informer de quelque chose. Elles ne sont pas traduites en code machine. Les utilisations courantes des directives sont : La définition de constantes La définition de mémoire pour stocker des données Grouper la mémoire en segment Inclure des codes sources de façon conditionnelle Inclure d'autres fichiers La directive equ La directive equ peut être utilisée pour définir un symbole. Les symboles sont des constantes nommées qui peuvent être utilisées dans le programme assembleur. Le format est le suivant : symbole equ valeur La directive %define En C, #define En assembleur: %define size 100 , remplace size par 100. mov eax, size Directives de données 20 Les directives de données sont utilisées dans les segments de données pour réserver de la place en mémoire. Il y a deux façons de le faire. 1) La première ne fait qu'allouer la place pour les données. Elle utilise la directive resx, ou x représente la taille d’objet à stocker. 2) La seconde alloue la place et donne une valeur initiale. Elle utilise la directive dx, ou x est la taille toujours. 21 Chapitre 4 : Architecture MIPS Introduction Ce chapitre propose une présentation élémentaire et générale de l'architecture du processeur MIPS. L'architecture MIPS est un ordinateur à jeu d'instructions réduit (RISC). Cela signifie qu'il y a un nombre plus restreint d'instructions qui utilisent un format d'encodage uniforme. Chaque instruction/opération effectue une seule tâche (accès à la mémoire, calcul, conditionnel, etc.). L'idée est d'optimiser l'exécution en faisant en sorte que le nombre d'instructions soit plus faible. En général, les architectures RISC, et plus particulièrement l'architecture MIPS, sont conçues pour des implémentations à haute vitesse. Aperçu de l'architecture Les composants de base d'un ordinateur comprennent une Unité Centrale de Traitement (CPU), une Mémoire Principale ou Mémoire Vive (RAM), un Stockage Secondaire (c'est-à-dire, un disque dur, un SSD, etc.), des périphériques d'Entrée/Sortie (c'est-à-dire, écran et clavier), et une interconnexion appelée BUS. Un schéma très basique de l'architecture d'un ordinateur est le suivant : Figure 10 : L’architecture étudiée Lorsqu'un programme est exécuté, il doit être copié du disque dur dans la mémoire RAM. Le CPU exécute le programme depuis la RAM. Cela est similaire à stocker un mémoire sur le disque dur, et lors de la rédaction/modification du mémoire, il est copié du disque dur dans la mémoire. Une fois terminé, la version mise à jour est enregistrée de nouveau sur le disque dur. 22 Types/Tailles de données Les types de données de base incluent les entiers, les virgules flottantes et les caractères. Cette architecture prend en charge des tailles de stockage de données en octets, en demi-mots (parfois appelés simplement demi) ou en mots. La virgule flottante doit être de taille de mot (32 bits) ou de double mot (64 bits). Les données de caractères sont généralement un octet et une chaîne est une série d'octets séquentiels. L'architecture MIPS prend en charge les tailles de données/mémoire suivantes : Nom taille byte 8-bits entier halfword 16-bits entier word 32-bits entire float 32-bits virgule flottante double 64-bits virgule flottante Table 1 : Taille et type de donnée Le demi-mot est souvent simplement appelé "half". Des listes ou tableaux (ensembles de mémoire) peuvent être réservés dans n'importe lequel de ces types. De plus, un nombre arbitraire d'octets peut être défini avec la directive ".space". Mémoire La mémoire peut être considérée comme une série d'octets, les uns à la suite des autres. Autrement dit, la mémoire est adressable par octets. Cela signifie que chaque adresse mémoire contient une information d'un octet. Pour stocker un mot, quatre octets sont nécessaires, utilisant quatre adresses mémoire. De plus, l'architecture MIPS telle que simulée dans QtSpim est en little-endian. Cela signifie que le byte de poids faible (LSB) est stocké à l'adresse mémoire la plus basse. Le byte de poids fort (MSB) est stocké à l'emplacement mémoire le plus élevé. 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 9 8 7 6 5 4 3 2 1 0 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 MSB LSB Table 2 : MSB and LSB 23 Par exemple, en supposant les déclarations suivantes : Num1 :.word 42 Num2 :.word 500000 Pour une architecture little-endian, l'image en mémoire serait la suivante : Nom du Valeur Adresse variab ? 0x100100C 00 0x100100B 4C 0x100100A 4B 0x1001009 Nom2 → 40 0x1001008 00 0x1001007 00 0x1001006 00 0x1001005 Nom1 → 2A 0x1001004 ? 0x1001003 Table 3: Image de la mémoire Selon l'architecture little-endian, le byte de poids faible (LSB) est stocké à l'adresse mémoire la plus basse et le byte de poids fort (MSB) est stocké à l'emplacement mémoire le plus élevé. Disposition de la mémoire La disposition générale de la mémoire pour un programme est comme indiqué : 24 Pile (partie haute) tas données non initialisées Données Texte code Réservée (partie basse) Table 4 : segmentation de la mémoire La section réservée n'est pas disponible pour les programmes utilisateur. La section du texte (ou du code) est l'endroit où le langage machine (c'est-à-dire les 1 et 0 qui représentent le code) est stocké. La section des données est l'endroit où les données initialisées sont stockées. Cela inclut les variables déclarées auxquelles une valeur initiale a été attribuée lors de l'assemblage. La section des données non initialisées est l'endroit où sont stockées les variables déclarées qui n'ont pas reçu de valeur initiale. Si elles sont accédées avant d'être définies, la valeur ne sera pas significative. Le tas est l'endroit où les données allouées dynamiquement seront stockées (si demandé). La pile commence en haute mémoire et se développe vers le bas. Le simulateur QtSpim ne fait pas de distinction entre les sections des données initialisées et non initialisées. Les sections suivantes fourniront des détails supplémentaires pour les sections du texte et des données. Registers du processeur Un registre de CPU, ou simplement registre, est un emplacement de stockage temporaire ou de travail intégré au CPU lui-même (distinct de la mémoire). Les calculs sont généralement effectués par le CPU en utilisant des registres. Le MIPS dispose de 32 registres d'entiers de 32 bits ($0 à $31) et de 32 registres à virgule flottante de 32 bits ($f0 à $f31). Certains des registres d'entiers sont utilisés à des fins spéciales. Par exemple, $29 est réservé pour être utilisé comme registre de pointeur de pile, désigné par $sp. Les registres disponibles et l'utilisation typique des registres sont décrites dans le tableau suivant. Les noms des registres transmettent des informations spécifiques sur leur utilisation. Les noms des registres seront utilisés dans le reste de ce document. Les sections suivantes approfondiront les conventions d'utilisation des registres et aborderont les registres 'temporaires' et 'sauvegardés'. Nom Nombre Utilisation registre registre 25 $zero $0 Matériel réglé à 0 $at $1 Assembleur temporaire $v0 - $v1 $2 - $3 Résultat de la fonction $a0 - $a3 $4 - $7 Registre d'argument 1 $t0 - $t7 $8 - $15 Registres temporaires $s0 - $s7 $16 - $23 Registres sauvegardés $t8 - $t9 $24 - $25 Registres temporaires $k0 - $k1 $26 - $27 Réservé au noyau SE $gp $28 Pointeur global $sp $29 Pointeur de la pile $fp $30 Pointeur de trame $ra $31 Adresse de retour Table 5: les différents registres du processeur avec leurs utilisations Registres réservés Les registres réservés suivants ne doivent pas être utilisés dans les programmes utilisateur. Nom registre utilité $k0 - $k1 Réservé au SE $at Assembleur temporaire $gp pointeur global $epc Compteur de programme d'exception Table 6: Registres réservés Les registres $k0 et $k1 sont réservés à l'utilisation par le système d'exploitation et ne doivent pas être utilisés dans les programmes utilisateur. Le registre $at est utilisé par l'assembleur et ne doit pas être utilisé dans les programmes utilisateur. Le registre $gp est utilisé comme pointeur vers les données globales (si nécessaire) et ne doit pas être utilisé dans les programmes utilisateur. 26 Registres Divers En plus des registres précédemment énumérés, il y a quelques registres divers qui sont répertoriés dans le tableau : Nom Registre Utilité $pc Compteur du pg $status ou $psw Registre d’état $cause Registre d’exception $hi Divisions et $lo multiplications Table 7 : Registres divers Le registre $pc ou compteur de programme pointe vers la prochaine instruction à exécuter et est automatiquement mis à jour par le CPU après l'exécution de chaque instruction. Ce registre n'est généralement pas directement accessible par les programmes utilisateur. Le registre $status ou registre d'état, également appelé $psw, est le registre d'état du processeur et est mis à jour par le CPU après chaque instruction. Ce registre n'est généralement pas directement accessible par les programmes utilisateur. Le registre $cause ou registre de cause d'exception est utilisé par le CPU en cas d'exception ou d'interruption inattendue dans le flux de contrôle du programme. Des exemples d'exceptions comprennent la division par 0, la tentative d'accès à une adresse mémoire illégale ou la tentative d'exécution d'une instruction non valide (par exemple, essayer d'exécuter un élément de données au lieu de code). Les registres $hi et $lo sont utilisés par certaines instructions de multiplication et de division spécialisées. Par exemple, un multiple de deux valeurs de 32 bits peut générer un résultat de 64 bits, qui est stocké dans $hi et $lo (32 bits chacun ou un total de 64 bits). Configuration du cœur CPU / FPU La table suivante présente une configuration de base de l'architecture interne du processeur MIPS Configuration du cœur de la puce FPU CPU Operations Operations réelles entières MIPS. Figure 11 : CPU/FPU L'unité de virgule flottante (FPU) est également appelée le coprocesseur FPU ou simplement 27 coprocesseur 1. Chapitre 5 : Déclarations de données et accès aux entrées sorties Déclaration et types de données Une variable est déclarée selon la syntaxe suivante : Identificateur :.Type valeur initiale En MIPS, on peut distinguer entre les types de données illustrées sur le tableau suivant : Déclaration Désignation.byte 8 bits.half 16 bits.word 32 bits.ascii Chaîne de caractères Ascii.asciiz Chaîne de carac Ascii terminée par NULL.float Nombre à virgule flottante 32 bits.double Nombre à virgule flottante 64 bits 28.space bytes mémoire non initialisées Table 8 : les différents types considérés par MIPS Exemples 1) Le type word Var1:.word 5000 Var2:.word -400 2) Le type chaîne de caractères Message :.asciiz ‘’hello world\n’’ 3) Les types flots et doubles X :.flloat -4.876 Y :.double 675.9876 Structure générale d’un programme.data Déclarations.text.globl main.ent main main: Corps du programe jr $ra Instructions load et store Instruction Désignation L Rdest, mem Stocke le contenu du mem dans Rdest Li Rdest, imm Stocke la valeu imm dans Rdest La Rdest, mem Stocke adresse dans Rdest S Rsrc, mem Store valeur de Rsrc dans mem 29 Table 9 : Instructions load et store Exemples Les instructions suivantes peuvent être utilisées li $t0, 27 sw $t0, num # num = 27 lw $t0, wnum sw $t0, wans # wans = wnum lh $t1, hnum sh $t1, hans # hans = hnum lb $t2, bnum Sb $t2, bans # bans = bnum Instruction Move Elle est utilisée pour déplacer la valeur d’un registre vers un autre registre Les différentes utilisations de l’instruction move sont illustrée dans le tableau suivant : Instruction Description move Rdest, RSrc Copier le contenu d’un registre entier vers un autre registre entier. mfhi Rdest Copier le contenu de $hi vers le registre Rdest mflo Rdest Copier le contenu de $lo vers le registre Rdest mthi Rdest Copier le contenu de Rdest vers le registre $hi mtlo Rdest Copier le contenu de Rdest vers le reg Copy the contents to the $lo 30 Table 10 : Instructions de copies Opérations Arithmétiques Instruction Description add Rdest, Rsrc, Src addition signée Rdest = Rsrc + Src ou Imm addu Rdest, Rsrc, Src Addition non signée Rdest = Rsrc + Src ou Imm sub Rdest, Rsrc, Src Subtraction signee Rdest = Rsrc – Src ou Imm subu Rdest, Rsrc, Src subtraction non signee Rdest = Rsrc – Src ou Imm mul Rdest, Rsrc, Src Multipli signée sans retenu Rdest = Rsrc * Src ou Imm mulo Rdest, Rsrc, Src Multipli signée avec retenu Rdest = Rsrc * Src ou Imm mulou Rdest, Rsrc, Src Multip non signée avec retenuRdest = Rsrc * Src ou Imm mult Rsrc1, Rsrc2 Multi signee 64-bit $hi/$lo = Rsrc1 * Rsrc2 multu Rsrc1, Rsrc2 Mult non signee 64-bit $hi/$lo = Rsrc1 * Rsrc2 Div Rdest, Rsrc, Src Division signee Rdest = Rsrc / Src or Imm Table 11 : Opérations Arithmétiques Entrées Sorties SPIM fournit un petit ensemble de services de type système d'exploitation par l'intermédiaire de l'instruction d'appel système syscall. Pour demander un service, un programme charge le code de l'appel système (voir Table ci-après) dans le registre $v0 et ses arguments dans les registres $a0,..., $a3 (ou $f12 pour les valeurs flottantes). Les appels systèmes qui retournent des valeurs placent leurs résultats dans le registre $v0 (ou $f0 pour les résultats flottants). Les chaînes de caractères 31 dans print_string et read_string sont à terminaison nulle. sbrk retourne un pointeur sur un bloc de mémoire contenant n octets supplémentaires et exit stoppe l'exécution d'un programme. Le tableau suivant fait la correspondance entre l’opération de lecture ou écriture, la valeur de $v0, les arguments et le résultat. Opération Valeur de $v0 Arguments Résultat Afficher entier 1 $a0=entier Afficher float 2 $f12=float Afficher double 3 $f12=double Afficher Chaîne car 4 $a0=entier Lire entier 5 $v0=entier Lire float 6 $f0=float Lire double 7 $f0=double Lire Chaîne car 8 $a0=entier, $a1=longue Table 11 : Les arguments des opérations de lecture et écriture pour les différents types 32 Sorties 1) Affichage d’une chaîne de caractères.data msg:.asciiz "Hi My friend".text.globl main.ent main main: li $v0,4 la $a0, msg syscall #Print string jr $ra #return 2) Affichage d’un entier.data msg1:.asciiz "Bonjour\n" x:.word 5643 y:.word -4532 msg2:.asciiz "Ok\n".text.globl main.ent main main: li $v0,4 # Affichage de la Chain de cara enregistrée dans $a0 la $a0, msg1 syscall #Print string li $v0,1 # Affichage d'un entier enregistrée dans $a0 33 lw $a0, x syscall li $v0,4 la $a0, msg2 syscall #Print string li $v0,1 lw $a0, y syscall jr $ra #return 3) Affichage d’une float.data x1 :.asciiz " ok" x2:.float -2.7 NewLine:.asciiz " ************* \n ".text.globl main.ent main main: # Lecture Float et stockage du résultat dans $f0 ***************** li $v0, 2 l.s $f12, x2 syscall jr $ra Entrées 1) Lire un entier.data x1 :.word 0 34 x2 :.word 12 NewLine:.asciiz " ************* \n ".text.globl main.ent main main: # Lecture Entier et stockage du résultat dans $v0 ***************** li $v0, 5 syscall sw $v0, x1 # Sauter la ligne *************************************** li $v0, 4 la $a0, NewLine syscall # Sauter la ligne *************************************** li $v0, 1 lw $a0, x1 syscall jr $ra 2) Lire une float.data x1 :.asciiz " ok" x2:.float -2.7 NewLine:.asciiz " ************* \n ".text.globl main.ent main 35 main: # Lecture Float et stockage du résultat dans $f0 ***************** li $v0, 6 syscall s.s $f0, x2 # Sauter la ligne *************************************** li $v0, 4 la $a0, NewLine syscall # Sauter la ligne *************************************** li $v0, 2 l.s $f12, x2 syscall jr $ra 36 Chapitre 6 : Instruction de branchement Syntaxe bcondiction, label1 b label2 Explication Exécuter le code équivalent au label1 si la condition est vérifiée, sinon exécuter le code équivalent au label2 Exemple 1 blt $t0,$t1, label1 b label2 label1 : pseudo-code1 label2 : pseudo-code2 Le tableau suivant illustre les différentes conditions appliquées sur les valeurs entiers avec les significations : Instruction Description beq , , Branche à étiqueter si et sont égaux bne , , Branche à étiqueter si et ne sont pas égaux blt , , Branche signée à étiqueter si est inférieur à ble , , Branche signée à étiqueter si est inférieur ou égal à bgt , , Branche signée à étiqueter si est supérieur à 37 bge , , Branche signée à étiqueter si est supérieur ou égal à bltu , , Branche non signée à étiqueter si est inférieur à bleu , , Branche non signée à étiqueter si est inférieur ou égal à bgtu , , Branche non signée à étiqueter si est supérieur à bgeu , , Branche non signée à étiqueter si est supérieur ou égal à Table 12 : mnémonique de branchement avec les différentes conditions Exemple 2 Le programme suivant permet de calculer la moyenne et la somme des éléments d’un tableau des entiers.data Tab:.word 1, 3, 5, 7, 9, 11, 13, 15, 17, 19 Size:.word 10 Som:.word 0 Moy:.word 0.text.globl main.ent main main: la $t0, Tab # Adresse d'initialisation de la table lw $t2, Size # longueur de la table li $t3, 0 # initialize somme=0 sumLoop: lw $t4, ($t0) # get array[i] add $t3, $t3, $t4 # sum = sum + array[i] add $t1, $t1, 1 # i = i+1 38 add $t0, $t0, 4 # Incrémenter par 4 octets blt $t1, $t2, sumLoop # Si i