Citation:
Envoyé par
tiloup367
Finalement je recherche une (je l'espère XD) dernière précision :
En mode 16bits, 2²⁰ octets sont adressables, donc 1048576 octets (1 Mo). Comment fonctionne la notation segment:offset?
Comme ceci :
+---+---+---+---+
| | | | | ← Offset (sur 16 bits)
+---+---+---+---+
+---+---+---+---+
+ | | | | | ← Segment (sur 16 bits)
+---+---+---+---+
-----------------------------
+---+---+---+---+---+
= | | | | | | ← Adresse physique (sur 20 bits)
+---+---+---+---+---+
Donc, en mode réel, le registre de segment est décalé de 4 bits vers la gauche (soit exactement un chiffre hexadécimal) par rapport à l'offset. Il « pèse » donc seize fois plus que le registre d'offset. Ces deux registres sont additionnés électroniquement pour former l'adresse physique qui va être directement envoyée sur les broches électriques du bus d'adresse (au moins sur les vieux modèles).
Donc, les couples 0010:0000, 0000:0100, 0001:00F0, 0005:00A0 ou 000F:0010, pour ne citer qu'eux, correspondent tous à la même adresse physique 00100.
Ça s'explique par le fait que lorsque le 8086 est apparu, les micro-processeurs 16 bits étaient déjà au point. Tous ses registres internes, y compris le pointeur de programme « IP » qui pointe en mémoire l'adresse de la prochaine instruction à exécuter étaient larges de seize bits ainsi que toute la circuiterie interne permettant de véhiculer leur contenu entre eux et vers la mémoire.
Un programme est donc « habitué » à voir une zone mémoire de 64 Ko. Même les micro-processeurs 8 bits des années 80 (Z80, 6809…) disposaient quand même de registres d'index de 16 bits (car un plan mémoire de 256 octets, c'est vraiment trop serré). Pour étendre l'espace utilisable, on utilisait couramment de la mémoire paginée telle que l'EMS sur PC : en gros des pages de mémoire de taille fixe et occupant toutes la même place et donc on choisissait la page active à un moment donné à l'aide d'un sélecteur, un peu comme quand on ouvre un tiroir d'une grande armoire.
Or, pour exploiter sur un tel matériel un bus d'adresse de 20 bits, il n'était pas concevable de développer des registres de 20 bits eux-aussi : c'est toute l'architecture qu'il aurait fallu adapter, ne serait-ce que pour pouvoir les charger, et faire des calculs dessus. En outre, « 20 » n'est pas une puissance de 2. Doter le 8086 de tels registres serait revenu à concevoir un nouveau micro-processeur depuis zéro.
Par contre, il était très facile d'utiliser deux registres de 16 bits chacun. Rajouter un tel registre à ceux déjà existants ne posait pas de difficulté particulière. Et plutôt que simplement concaténer ces registres et n'utiliser que les 4 bits de poids faible du registre de segment, il était beaucoup plus astucieux de les associer comme décrit ci-dessus.
D'abord, parce que si on souhaitait simplement ajouter quatre bits de manière linéaire, il suffisait d'utiliser les quatre bits de poids fort du registre de segment et non de poids faible. Ensuite — et surtout — parce que cela garantit la compatibilité ascendante en permettant de placer la zone visible de 64 Ko dont les programmeurs avaient déjà l'habitude n'importe où en mémoire avec une granularité de 16 octets.
C'est aussi la raison pour laquelle il est plus difficile de manipuler un registre de segment que tout autre registre : les manières de les charger ou les lire sont volontairement limités pour économiser les codes-opérations et parce qu'en général, on l'initialise une fois pour toute en début de programme pour ne plus s'en soucier ensuite.
C'est relativement simple et c'est évident une fois qu'on le sait. On comprend également que c'est une solution qui vient naturellement à l'esprit à toute personne confrontée à ce problème lors de la conception du micro-processeur. Toutefois, les « fameux segments » sont une question récurrente qui a causé bien des maux de tête aux étudiants et aux « amateurs avertis » dont je faisais partie à la fin des années 1980, surtout à une époque où Internet n'existait pas en France, en tout cas pas sous sa forme actuelle.
En mode protégé, maintenant, cela fonctionne un peu différemment : ce n'est plus directement le contenu du registre qui sert à calculer l'adresse mémoire physique, il ne s'agit que d'un index dans un table définie en mémoire et dans laquelle sont décrits différentes plages, dont la longueur et l'emplacement sont arbitraires. Il est même possible de déclarer deux plages strictement identiques.
Le fonctionnement est donc différent mais on a conservé les registres existants pour les utiliser à cette fin, ce qui est le plus intelligent à tous les niveaux puisque la technique « mode réel » n'est plus utilisable en mode protégé et que, sémantiquement, il s'agit toujours de la même chose : définir des plages de mémoire distinctes pour le code et les données, d'une part, et pour les différents programmes cohabitant sur la même machine en général.
Citation:
Est-ce que la valeur d'une adresse est en hexadécimal ou en décimal ou même octal (me surprendrais pour celle-ci) ou peu importe tandis qu'on respecte la limite d'adressage ?
Le décimal, l'hexadécimal, l'octal et même le binaire ne sont que différentes façons de représenter un même nombre. Tu pourrais également les écrire en chiffres romains si c'est plus clair pour toi. La seule base sur laquelle y est intéressant de se pencher est le binaire car c'est bien ainsi qu'une valeur va être physiquement et électriquement codée au sein de ta machine.
L'hexadécimal est utilisé car un chiffre hexadécimal correspond exactement à quatre bits. Il est donc très facile de convertir l'un vers l'autre et réciproquement car il suffit de convertir un à un chaque chiffre indépendamment des autres, sans avoir à faire de divisions successives.
L'octal servait à la même chose mais a été abandonné d'abord parce qu'il codait moins d'informations que le décimal et parce que chaque chiffre correspondait à trois bits, ce qui n'était vraiment pas pratique : ce n'est multiple ni de 8 bits (les octets), ni de 7 (courant sur les transmissions ASCII de l'époque), ni de 16. C'était pénible parce que pour représenter un octet, par exemple, il fallait trois caractères, ce qui permettait de représenter 512 combinaisons différentes et non 256. Il était donc pratiquement toujours possible d'écrire des valeurs invalides en octal avec les formats de données usuels, valeurs qu'il fallait alors contrôler et traiter, chose qui n'arrivait pour ainsi dire jamais en hexadécimal.
Les seuls intérêts de l'octal résidait dans le fait qu'on se cantonnait aux chiffres que l'on connaissait déjà et à une suite de symboles consécutives dans la table ASCII. L'hexadécimal étant beaucoup plus pratique à l'usage, il a fini par s'imposer.
Citation:
Je cherche a comprendre : est-ce que le segment de segment:offset représente une adresse de base sur laquelle on applique un décalage de X offset
Tout-à-fait. En « offset » veut dire « décalage » en anglais.
Citation:
et que rendu a ce décalage nous trouvons la case mémoire qui doit être de 2 octets (16 bits), donc soit une case code pour une instruction de 16 bits, soit une case donnée de 16bits ou bien une instruction 8bits et une donnée 8bits.
Non, sur Intel et sur la plupart des micro-processeurs grand public, une adresse mémoire correspond toujours à un octet de 8 bits, même si aujourd'hui et en interne, les bus sont plus larges (16, 32 et même 64 bits). La circuiterie électronique fait la conversion et extrait la donnée nécessaire. C'est également pour cela qu'aujourd'hui, l'alignement des données en mémoire sur des adresses multiples de quatre octets est prépondérante. Si on lit des mots de 32 bits mais alignés sur une adresse du style (n×4)+2, alors à chaque tour, on ne lit pas un mot de 32 bits mais deux demi-mots ! Deux fois plus de transactions bus que nécessaire + la conversion pour reconstruire la donnée initiale à partir de ses deux moitiés.
Citation:
Car dans l'exemple des 640 premiers Ko a la limite de A000:0000 -1, moi 0xA000 = 40960. donc +- 40Ko et non 640Ko. Car en hexadécimal, dans ma "logique d'incompréhension", 1048576 octets partent de 0000:0000 à 000F:FFFF donc FFFFF = 20bits bien remplis.
Comme tu l'as probablement compris, la solution est donnée au dessus : A000:0000 ne correspond pas à l'adresse physique 0A000 mais A0000, soit seize fois plus. Et 40 Ko × 16 font bien 640 Ko.
Citation:
Car voilà 3 ans, mes profs d'infos, pas tous, mais certains, disaient que l'espace la plus petite dans la mémoire était de 4 octets, c'est toujours d'actualité ou ? Car 4 octets, moi ça sonne mode 32 bits, donc mode 16 bits, des cases de 2 octets?
Oublie ceci pour le moment. C'est quelque chose qui devait être très dépendant du contexte et qui risque de ne t'apporter que confusion pour le moment.
Citation:
Envoyé par
tiloup367
Et qui, ma foi, 2Mo, en mode 16bits avec des programmes en ASM, devait être largement suffisant pour les besoins de l'époque. J'ai un choc lol, car un OS total en ASM doit rien prendre quand tu as 8 589 934 592 octets de dispo.
Et tu ne te trompes pas : sur mon TO8D de 1987, la totalité du « moniteur » (équivalent du BIOS), des deux langages BASIC intégrés en mémoire, de l'extra-moniteur (équivalent en ROM du DOS) avec gestion complète des périphériques comme les disquettes, les lecteurs de cassette (si, si), l'affichage graphique, les primitives écran (tracer des lignes, gérer les modes) mais aussi les fonctions plus évoluées comme la gestion des fichiers et toute la bibliothèque mathématique en virgule flottante (pas de coprocesseur à cette époque) avec, enfin, le menu de démarrage et les utilitaires intégrés de gestion graphique des fichiers, de réglage du crayon optique et de la palette de couleurs et le lanceur « d'applications » (émulation de cartouches) tenait en… 70 Ko !
Un simple fichier icône pèse aujourd'hui 2 à 3 fois plus lourd.