Accueil
Java Standard Edition
Java EE 5
Visual Basic .Net 2005
Visual C++ .Net 2005
Visual C# .Net 2005
Cours ASP .Net 2.0
Postgresql
Linux
Visual Studio 2008
ASP 3.0 Classique
Cours Javascript - DOM - DHTML
Cours Ajax
VBA
Assembleur
Perl
Membres
L'auteur du site
Nouveautés sur le site
Contacts
Plan du site
Exécution d'un programme
Les archives Jar
Les classes abstraites
Les interfaces
Les tableaux
La généricité
Les énumérations
Les classes internes
Classes anonymes et internes locales
E/S(1):InputStream et OutputStream
E/S(2):FileInputStream et FileOutputStream
E/S(3):Reader et Writer
E/S(4):FilterInputStream et FilterOutputStream
E/S(5):Les filtres d'octets: PrintStream
E/S(6):Les filtres d'octets: DataInputStream et DataOutputStream
E/S(7):Les filtres d'octets: BufferedInputStream et BufferedOutputStream
E/S(8):Flux de caractères: PrintWriter
E/S(9):Flux de caractères: FilterReader et FilterWriter
E/S(10):Flux de caractères: InputStreamReader, OutputStreamWriter, StreamDecoder, StreamEncoder
E/S(11):Flux de caractères: BufferedReader et BufferedWriter
E/S(12):Flux de caractères: FileReader et FileWriter
La classe String (java.lang)
Les collections: L'interface Collection(java.lang)
Les collections(2): L'interface List(java.util)
Les collections(3): AbstractCollection(java.util)
Les collections(4): AbstractList(java.util)
La bibliothèque Swing en Java
Les bases de données en Java
JDBC ( Java Database Connectivity )
Les interfaces graphiques
Les fichiers de configuration en Java
INSTALLATION JAVA EE 5, JRE 6, ECLIPSE, TOMCAT, ETC SOUS LINUX
INSTALLATION JAVA EE 5, JRE 6, ECLIPSE, TOMCAT, ETC SOUS WINDOWS
Les applications Web en java
Les filtres Java (javax.servlet.Filter)
I Généralités
I.1 Le formulaire principal
I.2 Les objets créés par Visual
I.3 Les variables références
I.4 Le garbage collector
II Créer évènements
II.1 Rappel évènements
II.2 Procédure à suivre
II.2.1 Créer son EventArgs
II.2.2 Créer EmetEvent
II.2.3 Déclarations autres
I Généralités
I.1 Applications winforms
I.2 Applications MFC
I.3 Objets managés ou pas
I.4 Objets non managés
I.5 Objets managés - handle
I.6 Le top-level ^
II Créer évènements
II.1 Rappel évènements
II.2 Procédure à suivre
II.2.1 Créer son EventArgs
II.2.2 Créer EmetEvent
II.2.3 Déclarations autres
I Généralités
I.1 Puissant et Accessible
I.2 Créer ses classes
II Créer évènements
II.1 Rappel évènements
II.2 Procédure à suivre
III Les services Windows
IV Le .net remoting
V Communication Tcp avec TcpClient et TcpListener
II.2.1 Créer son EventArgs
II.2.2 Créer EmetEvent
II.2.3 Déclarations autres
I Généralités
I.1 Un EDI formidable
I.2 Inclure C# ou VB
I.3 L'objet Response
I.4 Les évènements
II ASP .net et les bdd
II.1 Essayer plusieurs fois la requête
I 2.1 Fichiers distincts
I.2.2 Avec la balise script
I.2.3 Inclure réellement
I.2.4 Avec Response.Write()
I.3.1 La méthode Response.Redirect()
I.4.1 Résoudre problème post
Installation Postgre Linux
Cours Postgresql
Le Shell Unix( Linux, Ubuntu)
Les scripts C-Shell
Programmation système Unix
Reseau Linux
Les iptables
Windows Presentation Foundation(WPF)
Le Framework 3.0
Windows Workflow Foundation(WF)
ASP 3.0 Classique
Cours Javascript - DOM - DHTML
Chat Ajax
VBA Excel 2003
Assembleur
Perl
Inscription
Liste membres
Livre d'or
Forum
Accueil
>
Assembleur
>
Assembleur
____________________________________________________________________________________________________
Connexion
ASSEMBLEUR
14/02/2008
Sommaire :
I) Les registres 16 bits du 8086
II) Les registres 32 bits du 80386
III) Le mode protégé 16 bits
IV) Le mode protégé 32 bits
V) Les interruptions
VI) Le langage machine
VII) Le langage assembleur( ou assembleur, par abus de langage)
VIII) L’assembleur nasm
IX) Les directives de nasm
X) Usage du langage C combiné à l’assembleur, avec DJGPP
XI)Interfaçage avec le C : La convention d’appel C
XII) Les structures de contrôles
XIII)Les variables locales, suivant la convention d’appel C
XIV)Les nombres à virgule flottante
XV) Le coprocesseur arithmétique
Merci à tous les tutos du net sur lesquels je me suis appuyé, notamment le tuto du Dr. Paul A. Carter( qui est une référence pour la programmation assembleur en mode protégé 32 bits, car peu de documents existent sur l’assembleur en mode protégé).
Et aussi merci au cours d’assembleur du site de l’IUT de Caen. Même si je suis parti de ces sources, je crois apporter parfois des points de vues ou explications que je n'ai pas trouvé dans ceux-ci, donc mon tuto a une raison d'être.
I) Les registres 16 bits du 8086
a) Les registres généraux
Le microprocesseur 8086( la première génération, avec le 8088, des microprocesseurs de PC) possède 4 registres généraux de 16 bits. Ces registres sont AX, BX, CX et DX. On remarque que le début commence par les lettres de A à D, et que la fin et "X".
Chacun de ces registres peut être décomposé en deux registres de 8 bits. Par exemple, le registre AX peut être découpé en AH et AL. H comme High et L comme LOW. AH, c'est donc les 8 bits de poids forts du registre AX, et AL les 8 bits de poids faibles de AX. En changeant la valeur de AH, on change par conséquent la valeur de AX.
De même, en changeant la valeur de AX, on change la valeur de AH et de AL! On utilise généralement ces regitres 8 bits comme des regitres indépendants.
Pourquoi des registres? Les registres servent à placer une valeur, ce sont donc l'équivalent des variables en programmmation de plus haut niveau. Le microprocesseur met moins de temps à accéder au contenu des registres, qu'à accéder au contenu de la mémoire, car les registres se situent dans le microprocesseur,et non à l'extérieur.
Pour les besoins courants, c'est donc une bonne idée de laisser à disposition quelques variables, dont l'accès est très rapide.
Pourquoi ces registres 16 bits se découpent-ils en 2 registres 8 bits? Avec le même registre 16 bits du microprocesseur, on peut utiliser au choix un registre 16 bits ou deux registres 8 bits. Donc on peut avoir au choix une "grande" variable ou deux petites variables, selon le besoin. On dispose donc de plusieurs outils, avec la même ressource du processeur( cette ressource est le registre), donc on profite au maximum de cette ressource!
Cette idée de profiter au maximum des ressources du microprocesseur se rencontre continuellement.
De plus, il peut parfois arriver qu'on veuille obtenir les 8 bits de poids forts(ou de poids faibles) d'une valeur 16 bits: encore un intérêt. Les nombres étant stockés en base 2 dans les ordinateurs, il est très facile pour un ordinateur de donner les 8 bits de poids forts ou de poids faibles d'une valeur 16 bits: il lui suffit de lire 8 des bits au lieu de 16 bits.
b) Les registres de pointeurs
b.1) Les registres d'index
Il existe deux registres d'index 16 bits: SI et DI. Ces registres sont utilisés comme des pointeurs, mais peuvent aussi servir de registres généraux: ici aussi on profite au maximum des ressources du microprocesseur. SI = Source index( index source), et DI = Destination Index( index de destination). On remarque qu'une sémantique( destination ou source) est rattachée au registre d'index. Comme on ne peut pas choisir le nom des registres, c'est une manière de pallier à cet handicap. C'est comme si on ne vous donnait pas la possibilité de choisir le nom de vos variables, mais qu'en contrepartie, on vous donnait des variables avec un nom prédéfini. Mais cette sémantique n'est pas obligatoire: la preuve est qu'on peut utiliser ces deux registres d'index comme des registres généraux.
Les registres SI et DI ne se décomposent pas en deux registres de 8 bits( et c'est logique, car leur rôle prévu est quand même d'être un pointeur; d'ailleurs index est un synonyme de pointeur).
b.2) Les registres de pointeur
Les registres SP et BP sont deux registres 16 bits qui contiennent des pointeurs sur un emplacement mémoire de la pile.
La pile( stack) est une zone de mémoire.
b.2.a) Le registre SP( stack pointer)
SP est appelé pointeur de pile( stack pointer; stack = pile). SP est un registre 16 bits qui pointe sur le haut de la pile. Pour une pile non vide, SP pointe sur le dernier élément empilé. Si la pile est vide, SP pointe sur l'emplacement où sera contenu le prochain élément empilé.
b.2.b) Le registre BP( base pointer)
BP est appelé pointeur de base(base pointer). BP est un registre 16 bits qui sert comme registre pour pointer sur une donnée de la pile, quand on a besoin d'un registre temporaire pour pointer sur cette donnée.
b.2.c) Le registre IP( Instruction Pointer = pointeur d’instruction)
Ce registre pointe sur l’adresse de la prochaine instruction à exécuter. Avec le registre CS, on a l’adresse complète. Ce registre est utilisé par le processeur pour connaître l’adresse de l’instruction qu’il va exécuter. IP est incrémenté à chaque exécution d’instruction, ou alors en cas de saut ou de call, c’est l’adresse de saut qui est mise dans IP. C’est logique que c’est au moment de l’exécution de l’instruction qu’on est le mieux placé pour calculer la prochaine adresse à exécuter. C’est pour cette raison que IP est mis à jour juste après chaque exécution d’instruction, car c’est à ce moment là qu’on connaîtra la prochaine adresse( incrémentation ou adresse du saut si saut il y a). Le registre IP n’est pas directement utilisable.
b.3) Les registres de segment
Il y a 4 registres de segments: CS, DS, SS, ES. Ce sont des registres 16 bits. CS = Code Segment; DS = Data Segment; SS = Stack Segment; ES = Extra Segment. Vous avez certainement remarqué que les registres de pointeur que nous avons vus sont des registres de 16 bits seulement. Avec 16 bits, on peut adresser seulement 64 Ko. Il faut donc un système pour étendre notre capacité d'adressage. C'est là qu'interviennent les registres de segment, qui vont dire sur quelle zone de mémoire on travaille. Puis le registre de pointeur affinera l'adresse: il donnera le déplacement(offset). Comment obtenir l'adresse réelle à partir du segment + du déplacement? ce n'est pas direct, nous l'expliquerons dans le paragraphe suivant. Mais toujours est il qu'à partir de ce couple segment/offset, nous pouvons obtenir l'adresse réelle.
Les registres de segment indiquent quel segment est utilisé pour les différentes parties d'un programme. Le registre CS contient le numéro de segment de mémoire qu'on utilise pour le code. DS le segment utilisé pour les données.
SS le segment de la pile. ES est un registre de segment temporaire( d'où son nom).
b.3.a) La mémoire en mode réel
Le microprocesseur 8086 ne connait que le mode réel, contrairement à des processeurs plus récents, qui connaissent le mode protégé.
Le mode réel est une façon de définir l'adressage mémoire. Ce mode est tombé en désuétude. Il permet d'adresser au maximum 1Mo de mémoire(seulement!). La mémoire est adressé par un couple segment:offset. Le segment et l'offset sont chacun sur 16 bits. Le numéro de segment est aussi appelé selecteur.
On remarque que pour adresser 1Mo, il faut 5 chiffres hexa: de 00000 à FFFFF( car avec 20 bits, on peut représenter 1048576 valeurs(65536*16)). C'est donc suffisant car 1Mo=1024*1Ko, = 1024*1024= 1048576 octets, donc c'est parfait!.
b.3.a.2) Le couple segment:offset
En mode réel, la mémoire est découpée en segments de 64Ko. Seulement, il y a 65536 segments: donc les segments se chevauchent. La logique aurait voulu qu'il y ait 1048576 / 64Ko = 16 segments de 64Ko. Dans ce cas, les segments ne se seraient pas chevauchés. Or ce n'est pas ce qui est utilisé. Les segments se chevauchent.
Comme il y a 65536 segments; le numéro de segment a besoin de 16bits. Et comme chaque segment a une longueur de 64Ko, le déplacement(offset) a besoin de 16bits.
Comme il y a 65536 segments( donc le nombre maximal de segments, pour qu'on puisse avoir un numéro sur 16 bits, a été choisi) pour 1Mo, tous les 1Mo/64Ko=16 octets débute un nouveau segment. Pour retrouver l'adresse physique de début de segment, on fait numéro_segment*16. Et pour retrouver l'adresse physique à partir d'un couple segment:offset, on rajoute le déplacement à l'intérieur de ce segment, déplacement qui est de 64Ko, car chaque segment est d'une taille de 64Ko.
On a en résumé: adresse physique = 16*segment + offset.
Le couple segment:offset permet donc de retrouver une adresse physique de 20 bits.
Par exemple, l'adresse physique qui est référencée par 053E:A15B est 073E * 10h = 73E0 + A15B = 1153B ou 70971 en décimal.
073E = 1854 en décimal. A15B = 41307 en décimal. 073E * 10h = 73E0( facile, il suffit de décaler d'un chiffre vers la gauche pour multiplier par 16). 73E0 = 29664 en décimal. 73E0+A15B = 29664+41307=70971 en décimal.
On remarque qu'une même adresse physique peut être écrite de plusieurs manières différentes. A partir d'un couple segment:offset, une seule adresse physique correspond( c'est le principal, sinon ce système de codage ne nous intéresserait pas! Car l'objectif est bien d'écrire les adresses physiques avec 2*16 bits). Mais à partir d'une adresse physique, il y a plusieurs couples segment:offset possibles. Démonstration: tant qu'on a un offset avec une marge restante >=16 octets, on peut diminuer le segment de 1, et augmenter l'offset de 16! Par exemple, le couple 5000:0001, peut s'écrire 4000:0010, ou encore 3000:0100, ou encore 2000:1000, soit 4 façons différentes d'écrire l'adresse physique 50001h(h comme hexa)(50001h=327681 en décimal).
b.3.a.2) Pourquoi avoir choisi ce système de codage?
Un avantage est que pour retrouver l'adresse physique, on a juste à multiplier par 16 le numéro de segment( et rajouter l'offset).
Par ailleurs, si on avait pris des segments de 65536 octets, on aurait eu 16 segments, et le couple segment:offset aurait été unique. Avec des segments de 16 octets, on a 65536 segments, donc le nombre maximal de segments possibles. Intel a donc cherché à maximiser le nombre de segments. Avec 65536 segments, on exploite au maximum les 16bits des registres de segments, tout en utilisant également les 16 bits de l'offset( car les segments font tout de même 64Ko). On a donc un système de codage de l'adresse physique qui exploite au maximum le couple 16 bits/16bits. Un avantage de maximiser le nombre de segment est que, rien qu'avec le numéro de segment, on a l'adresse physique, à 16 octets près. Ce qui est la précision maximale qu'on aurait pu espérer pour un numéro de segment en ayant 16bits pour pouvoir coder les numéros de segment. Si on avait que 16 segments, avec le numéro de segment, on aurait eu l'adresse physique à 64Ko près. Alors qu'avec 65536 segments, on a l'adresse physique à 16 octets près, ce qui est 4096 fois plus précis.
Quant à l'offset, quelque soit le nombre de segments qu'on aurait choisi, il aurait toujours représenté le déplacement en octets dans ce segment, car les segments auraient toujours fait 64Ko, dans tous les cas!
Il est logique d'avoir cherché à maximiser le nombre de segments, car chaque programme a une valeur CS, DS, et SS.
Et chaque programme est susceptible d'utiliser les 64Ko de ses segments. Or, plus on a de segments, plus on peut mettre de programmes différents dans la mémoire. Avec 16 segments, ca aurait été très peu! Et n'oublions pas, comme nous le verrons bientôt, qu'un programme peut dépasser ses 64Ko, et utiliser d'autres segments. Tout ceci nous démontre que la maximisation du nombre de segment est souhaitable.
b.3.a.3) Inconvénients de la segmentation en mode réel
- Comme vu précédemment, une même adresse physique correspond à plusieurs adresses segmentées.
- La taille de 64Ko par segment à des conséquences:
* Si les données sont contenues dans plus de 64Ko, une unique valeur de DS n'est pas suffisante. On doit changer la valeur de DS si on veut des données d'un autre segment.
* De même, si le programme occupe plus de 64Ko, une unique valeur de CS ne suffit pas. On doit changer la valeur de CS quand le programme exécute du code se trouvant dans un autre segment.
b.4) Le registre FLAGS
C’est un registre dont les bits ont une signification propre. Ce registre contient des indications sur le déroulement de l’instruction précédente. Le registre FLAGS n’est pas directement utilisable. Le microprocesseur veut mettre à notre disposition des indicateurs. Ces indicateurs sont des bits. Par exemple, le bit Z, qui est mis à 1 lorsque le résultat de l’instruction précédente était zéro. Ces bits indicateurs, il faut bien qu’ils soient quelque part. On a donc choisi de les placer dans un registre du microprocesseur, un registre spécial. Ce registre est le registre FLAGS. Ces indicateurs sont l’équivalent de tests faits automatiquement, par exemple le test « dernier résultat = 0 ? », pour le le bit Z.
Mais toutes les instructions ne modifient pas forcément le registre FLAGS.
II)Les registres 32 bits du 80386
A partir du processeur 80386, les registres du microprocesseur se sont étendus, et sont passés à 32 bits au lieu de 16 bits. Les registres AX, BX, CX et DX deviennent respectivement EAX, EBX, ECX et EDX. Les registres BP et SP deviennent EBP et ESP. Le registre IP devient EIP. SI et DI deviennent ESI et EDI. FLAGS devient EFLAGS.
Les anciens registres AX, BX, CX, DX, SI et DI sont gardés, pour rester compatibles. Contrairement à EBP, ESP, EIP, EFLAGS, dont les versions 16 bits n’existent plus.
Les registres de segments( CS, DS, ES, SS) sont restés sur 16 bits, mais on a rajouté deux registres de segments généraux( comme ES) : FS et GS, qui n’ont pas de signification précise d’utilisation(ce sont des registres de segments temporaires).
AX forme les 16 bits de poids faibles de EAX, et on ne peut pas récupérer les 16 bits de poids forts de EAX de manière directe.
III)Le mode protégé 16 bits
Le processeur 80286 a introduit le mode protégé 16 bits.
Ecrivons ici la structure d’un descripteur de segment. Nous expliquerons ce qu’est un descripteur de segment dans les explications du mode protégé 32 bits. Donc revenez aux explications ci-dessous après avoir vu le chapitre sur le mode protégé 32 bits.
Image venant du site de l’IUT de Caen
La taille du descripteur de segment est de 8 octets.
On remarque que la longueur du segment est sur 16 bits. La taille d’un segment peut aller par conséquent jusqu’à 64 Ko. Et nouveauté : la taille peut aller de 1 octet à 64Ko, elle n’est pas figée à 64Ko comme en mode réel. D’ailleurs, si elle était figée, il n’y aurait pas de champ longueur dans le descripteur de segment ! De toutes façons, la taille d’un segment ne peut être que de 64Ko maximum, car le déplacement(offset) est sur 16 bits pour le microprocesseur 80286.
Les deux premiers octets sont réservés aux 80386, nous les verrons dans le prochain chapitre. Ils sont inutilisés pour le microprocesseur 80286.
L’adresse de segment est sur 24 bits( 16 + 8). La mémoire adressable est donc de 2 puissance 24 = 16Mo(théoriquement, selon moi, 16Mo + 64Ko taille offset), ce qui est d’ailleurs la capacité mémoire maximale que peut adresser un 80286 !
La taille limitée à 64 Ko des segments est un gros problème du 286.
Le système de mémoire virtuelle existe(nous verrons la mémoire virtuelle dans le chapitre sur le mode protégé 32 bits). Lorsqu’un segment est remis depuis le disque, vers la mémoire, il sera en général placé à un autre endroit de la mémoire que sa place précédente. Mais il concernera toujours le même descripteur de segment. Tout ce travail est fait de manière transparente.
IV)Le mode protégé 32 bits
Le processeur 80386 a introduit le mode protégé 32 bits.
La segmentation est toujours présente comme dans le mode réel, mais elle est programmable. En mode réel, le sélecteur était un numéro de segment. Ici, le sélecteur devient un indice dans une table de descripteurs de segments( appelée « tableau des descripteurs »). Le sélecteur est toujours sur 16 bits, comme en mode réel. D’ailleurs, on a remarqué que les registres de segments( CS, DS, SS, ES, et les nouveaux FS et GS ) étaient toujours sur 16 bits.
L’adresse mémoire que le programmeur indiquera( appelée adresse virtuelle) sera donc formée d’un couple sélecteur sur 16 bits et offset sur 32 bits. L’offset est contenue par exemple dans les registres 32 bits comme EBP, ESI etc. Et le sélecteur sera, bien sûr, dans un registre de segment.
Les segments ne sont plus à des positions fixes en mémoire, comme en mode réel. On désigne ici le segment par son indice de sélecteur, ce qui permet d’introduire une souplesse. On peut dès lors changer le segment réel en mémoire utilisé, quand on veut, puisque l’indice de descripteur, lui, ne changera pas. On peut aussi décider que ce segment utilisé ne se trouvera plus en mémoire, mais sur un disque dur par exemple( il faut alors, bien entendu, dire où il se trouve sur le disque). C’est donc une autre forme de souplesse introduite, qui permet d’avoir le système de mémoire virtuelle.
Initialement( en mode réel), la segmentation avait pour raison d’être initiale de pallier au fait qu’on ne disposait que de registres 16 bits pour adresser. L’adresse était alors découpée, en quelques sortes, en deux registres 16 bits. En mode protégé 32 bits, cette raison d’être de la segmentation reste vraie. La segmentation permet encore de pallier à la petitesse des registres(32 bits ici), et permet de découper l’adresse en un registre 16 bits couplé à un registre 32 bits.
IV.a) Remarque sur la mémoire virtuelle
Le principe premier de la mémoire virtuelle est de ne plus laisser en mémoire les programmes et les données qui ne sont pas utilisés pour le moment, et de les sauvegarder sur le disque provisoirement jusqu’à ce qu’ils soient demandés à nouveau. Comment savoir qu’un programme n’est pas utilisé, c’est une autre question. Mais le principe est bon : on retire de la mémoire ce qui n’est pas utilisé pour le moment. Car ces choses inutilisées occupent de la mémoire inutilement. Et la mémoire étant toujours limitée sur les ordinateurs, on peut les retirer, puisque ces choses ne servent pas. C’est évident. On gagne alors de la mémoire !
On appelle fichier de swap ou fichier d’échange, le fichier sur le disque dur qui contient les informations qui étaient en mémoire. Pourquoi échange ? Car ce fichier sert à faire des échanges RAM -> disque dur et aussi disque dur->RAM.
IV.b) Retour sur le mode protégé
Revenons sur le schéma du descripteur de segment ci-dessus, dans le chapitre sur le mode protégé 16 bits. Nous pouvons maintenant expliquer les deux octets réservés pour le 386( les deux premiers).
Le premier octet à gauche contient les bits 24 à 31 de l’adresse de segment(appelée aussi adresse de base). La mémoire adressable est de 2 puissance 32 = 4Go, puisque l’adresse de segment forme l’adresse de base(théoriquement, selon moi, 4Go + 1 Mo taille offset).
Un segment peut faire jusqu’à 1 Mo. D’ailleurs la longueur du segment, dans le descripteur de segment, est comprise sur 16+4 = 20 bits.
Le déplacement(offset) devient sur 32 bits(n’oubliez pas les registres étendus), donc théoriquement la taille d’un segment peut aller jusqu’à 4 Go. Ceci peut paraître paradoxal car la longueur du segment, dans le descripteur de fichier, est sur 20 bits, donc est de 1 Mo maximum. Il y a une explication à cela ! Il y a un bit, dans le descripteur de segment, qui est le bit 7 de l’octet de droite des 2 octets réservés pour le 386, qui est appelé bit de Granularite. Il sert à indiquer comment interpréter la taille du segment indiquée. Si le bit est 0, la taille est en octet, et peut donc aller de 1 octet à 1Mo. Si le bit est à 1, la taille peut aller de 4 Ko à 4Go, par incréments de 4Ko.
Le bit 2 est le bit TI( Table Indicator), il sert à indiquer de quel table de descripteur de segment on parle( eh oui, il peut y en avoir plus d’une table de descripteurs de segments). Si le bit est à 0, il s’agit de la GDT( Global Descriptor Table). Si le bit est à 1, il s’agit d’une des optionnelles LDT(Local Descriptor Table), et plus précisément de la LDT courante.
Les bits 1 et 0 sont le niveau de privilège du sélecteur( varie de 0 à 3). La plupart des systèmes d’exploitation modernes ne se servent que de deux de ces niveaux : le plus libre, le niveau 0, appelé mode noyau. Et le niveau 3, le plus restrictif, appelé aussi mode utilisateur. Il peut paraître étonnant que ce soit le programmeur qui donne le niveau de privilège, mais je n’ai pas pour l’instant de réponse à cette question, à moins que ces bits soit positionnés automatiquement en mode utilisateur, par le système d’exploitation par exemple, lors des demandes d’accès à la mémoire.
IV.c) Mécanisme de pagination
Depuis le mode protégé 32 bits( c'est-à-dire depuis le 386), un mécanisme de pagination a été introduit. Il s’agit d’un mécanisme de plus bas niveau que le mécanisme de segmentation, et qui est transparent. La mémoire est alors découpée en pages de 4Ko chacune. 4Go de mémoire représentent alors 1024*1024 pages. On peut décrire des informations sur chacune de ces pages, en créant un système de tables, sur le même principe que les tables de descripteur de segment. On utilise une table appelée répertoire de pages( page directory), contenant 1024 entrées. Chacune de ces entrées est un pointeur vers une table de pages( page table), qui elle contient les informations sur les pages( une table de pages a 1024 entrées, et concerne donc 1024 pages). On retrouve donc bien 1024 tables de pages * 1024 pages = 1024*1024*4Ko = 4Go. Pour retrouver les informations sur une page, il suffit donc de trouver, dans le répertoire de pages, le pointeur sur la bonne table de pages. Puis, dans la table de pages, il suffit de lire l’entrée correcte (correspondant à la page cherchée).
Le mécanisme de pagination n’a pas les mêmes objectifs que le mécanisme de segmentation. Il sert à la gestion de la mémoire virtuelle, et aux allers-retours vers le fichier de swap. Alors que le mécanisme de segmentation, comme indiquée ci-dessus, a pour rôle notamment de diviser une adresse pour s’adapter à la petite taille des registres. Mais aussi il permet d’avoir le mécanisme des descripteurs de segments, qui permet d’avoir des adresses de segments qui peuvent changer, tout en gardant le même sélecteur de segment. La pagination est donc de plus bas niveau, et est presque du même niveau que la mémoire elle-même.
Les segments sont donc divisés en pages de 4Ko. Et la mémoire virtuelle se sert des pages au lieu des segments, car cela permet de ne pas être obligé d’avoir l’intégralité du segment en mémoire, comme en mode protégé 16 bits. Le système des pages permet de ne charger en mémoire que certains morceaux du segment, et étant donné que les segments peuvent être très grands en mode protégé 32 bits, cela est très important. De plus, seules certaines parties du segment sont sauvegardées sur disque dans le cadre de la mémoire virtuelle, et pas obligatoirement la totalité( donc le fichier de swap sera moins grand, et les durées de sauvegarde et de chargement également).
La pagination est donc un mécanisme transparent destiné à assouplir le système des segments, et à faciliter l’implémentation du système de mémoire virtuelle. Une page, c’est comme une page d’un livre. Un livre est divisé lui aussi en pages ! Ainsi, on n’est pas obligé d’avoir tout le livre en mémoire(tout le segment), si on est intéressé uniquement par deux phrases d’une page, on n’aura alors que la page en question du livre. C’est sur ce principe qu’est basée la pagination.
On n’expliquera pas la pagination plus en détail pour le moment, mais ce que nous en savons est suffisant, il n’est pas indispensable de comprendre la totalité du mécanisme de pagination, connaître le principe général est suffisant.
V) Les interruptions
Quand une interruption survient, le microprocesseur arrête l’exécution du programme courant. Puis le microprocesseur sauvegarde le contexte dans lequel il était( c’est-à-dire des données indispensables pour rétablir le microprocesseur ensuite dans les mêmes conditions qu’on était au moment de l’interruption). Et enfin, le microprocesseur exécute une routine de traitement de l’interruption. Cette routine est appelée routine d’interruption( ou encore handler d’interruption). Quand la routine d’interruption a terminé de s’exécuter, le microprocesseur reprend l’exécution du programme, à l’endroit où il s’était arrêté, et en restaurant le contexte précédemment sauvegardé.
V.a) Plusieurs types d’interruptions
Il y a plusieurs types d’interruptions : les interruptions matérielles, les interruptions logicielles, et les exceptions.
On peut ajouter qu’on appelle interruption externe, les interruptions qui proviennent de l’extérieur du processeur. Les périphériques génèrent ces interruptions( par exemple le clavier). Alors que les interruptions internes sont déclenchées par le processeur, par exemple après une instruction INT.
V.a.1) Les interruptions matérielles
Les interruptions matérielles sont déclenchées par un composant électronique de l’unité centrale. Un certain évènement a lieu, et cela provoque le déclenchement d’une interruption matérielle par un composant de l’unité centrale. Cela peut être, par exemple, un appui sur une touche du clavier.
Plusieurs interruptions matérielles peuvent avoir lieu en même temps, c’est pour cela qu’un circuit électronique appelé contrôleur d’interruption ou PIC(Programmable Interrupt Controler) est présent. PIC = contrôleur d’interruption programmable, en français. Le contrôleur d’interruption reçoit donc tous les signaux d’interruption des composants. Puis, suivant l’origine du signal d’interruption, il attribut une priorité, et envoie au microprocesseur( par l’intermédiaire du bus de données) le numéro de la routine d’interruption( c'est-à-dire le numéro de l’interruption) dont la priorité est la plus forte(c’est logique).
Une demande d’interruption est appelée aussi IRQ(Interrupt Request).
Le 8088 utilisait comme PIC un composant électronique numérique qui était le I8259.
Le Intel 8259 du 8088 pouvait traiter jusqu’à 8 demandes d’interruptions au même moment, et disposait d’ailleurs de 8 entrées, appelées IRQ(0) à IRQ(7).
Les 286, 386 et 486 utilisaient deux 8259 chaînés, et disposaient donc de 16 interruptions possibles. Etendre le nombre d’interruptions simultanées possibles est important car cela étend et ouvre les capacités de l’ordinateur.Ici, chaque contrôleur peut gérer 8 périphériques différents. En effet, une entrée est suffisante pour gérer un périphérique entier, car tout ce dont le périphérique a besoin, c’est uniquement de signaler, de déclencher une interruption. Les données à propos de cette interruption ne sont pas envoyées de cette façon, le problème est juste de signaler une interruption.
A partir du pentium 1, le contrôleur d’interruption est intégré dans le chipset( attention, chipset ne signifie pas microprocesseur), ce n’est plus un circuit spécialisé.
V.a.1.a) Définition du chipset :
Le chipset est apparu avec le pentium 1, et gère l’ensemble des communications entre le processeur et les composants. C’est un des composants électroniques essentiel de la carte mère. Le chipset évite d’avoir des composants spécialisés pour chaque fonction, et réduit donc le nombre de circuits implantés sur la carte mère.
V.a.2) Les interruptions logicielles
Une interruption logicielle est déclenchée par un programme en cours d’exécution dans le processeur. Cette interruption provoque alors l’interruption( n’oublions pas que « interruption » veut dire « interrompre ») du programme en cours d’exécution, et l’exécution de la routine d’interruption dont le numéro a été demandé. La routine d’interruption est une routine du DOS ou du BIOS.
Pour déclencher une telle interruption logicielle,