Pourquoi la première instruction du BIOS se trouve-t-elle à 0xFFFFFFF0 («haut» de la RAM)?

51

Je sais que le BIOS charge sa première instruction à partir de 0xFFFFFFF0, mais pourquoi cette adresse spécifique? J'ai de nombreuses questions et j'espère que vous pourrez m'aider avec au moins certaines d'entre elles.

Mes questions:

  • Pourquoi la première instruction du BIOS se situe-t-elle au "sommet" d'une mémoire vive de 4 Go?
  • Que se passerait-il si mon ordinateur ne disposait que de 1 Go de RAM?
  • Qu'en est-il des systèmes dotés de plus de 4 Go de RAM (par exemple, 8 Go, 16 Go, etc.)?
  • Pourquoi la pile est-elle initialisée avec une valeur (dans ce cas, une valeur située à 0xFFFFFFF0)?

J'ai lu à ce sujet cet après-midi et je ne comprends toujours pas.

Fernando Paladini
la source
28
Une question par question s'il vous plaît.
Lightness Races avec Monica
4
J'aime la façon dont la réponse acceptée ne mentionne même pas la mémoire segmentée ou les modes d'adressage, et le seul endroit où la ligne A20 est même touchée est dans les commentaires.
imallett
Les AVR Atmel commencent l’exécution à partir de l’adresse 0, alors que Freescale HCS08 est démarré à partir de 0xFFFE, iirc. Chaque famille de processeurs a ses propres caractéristiques.
Nick T
2
@imallett J'aime bien comment vous décidez de vous plaindre ici plutôt que de demander à l'affiche de mettre à jour sa réponse avec des informations supplémentaires. J'aime aussi la façon dont vous pensez que cette connaissance qu'OP pourrait identifier, même si le but de poser une question est d'obtenir des informations sur des éléments que l'on pourrait maintenant parfaitement comprendre.
MonkeyZeus
2
@ MonkeyZeus à ce jour, 9 autres commentateurs l'ont déjà fait et cela n'a toujours pas changé. Mon commentaire, bien que sarcastique, n’était pas vide; c'est un avertissement pour les futurs internautes, ainsi que pour le PO.
imallett

Réponses:

57

0xFFFFFFF0est l'endroit où un processeur compatible x86 commence à exécuter des instructions lorsqu'il est allumé. Il s’agit d’un aspect câblé, non modifiable (sans matériel supplémentaire) de la CPU et différents types de CPU se comportent différemment.

Pourquoi la première instruction du BIOS se situe-t-elle au sommet d'une RAM de 4 Go?

Il se situe au sommet de l' espace d'adressage de 4 Go . À la mise sous tension, le BIOS ou la ROM UEFI est configuré pour répondre aux lectures de ces adresses.

Ma théorie sur pourquoi c'est:

À peu près tout dans la programmation fonctionne mieux avec des adresses contiguës. Le concepteur de la CPU ne sait pas ce qu'un constructeur de système voudra faire avec la CPU. Il est donc déconseillé pour la CPU d'exiger que les adresses situées au milieu de l'espace soient utilisées à des fins diverses. Il est préférable de garder cela "à l'écart" en haut ou en bas de l'espace d'adressage. Bien sûr, gardez à l'esprit que cette décision a été prise lorsque le 8086 était nouveau, et qu'il ne possédait pas de MMU .

Dans le 8086, des vecteurs d'interruption existaient à l'emplacement de mémoire 0 et supérieur. Les vecteurs d'interruption doivent se trouver à des adresses connues et doivent être stockés dans la RAM pour plus de flexibilité. Cependant, le concepteur de la CPU n'a pas été en mesure de connaître la quantité de RAM allouée dans un système. Donc, partir de 0 et travailler vers le haut était logique pour ceux-ci (car aucun système en 1978, lorsque le 8086 a été inventé, aurait 4 Go de RAM - attendre donc que la RAM soit à 0xFFFFFFF0 n’était pas une bonne idée), et ensuite ROM devrait être à la limite supérieure.

Bien entendu, à partir d’au moins 80286, les vecteurs d’interruption pourraient être déplacés vers un emplacement de départ différent de 0, mais les processeurs modernes 64 bits x86 démarrent toujours en mode 8086, de sorte que tout fonctionne toujours à l’ancienne pour des raisons de compatibilité (aussi ridicule que possible). comme il semble en 2015 avoir encore besoin de votre processeur x86 pour pouvoir exécuter DOS).

Ainsi, étant donné que les vecteurs d'interruption commencent à 0 et vont vers le haut, la ROM devrait partir du haut et aller vers le bas.

Que se passerait-il si mon ordinateur ne disposait que de 1 Go de RAM?

Une CPU 32 bits a 4 294 967 296 adresses numérotées de 0 (0x00000000) à 4294967295 (0xFFFFFFFF). La ROM peut vivre dans certaines adresses et la RAM dans d'autres. Avec la MMU du processeur, vous pouvez même l'activer à la volée. La RAM n'a pas à vivre à toutes les adresses.

Avec seulement 1 Go de RAM, certaines adresses n’auront rien à répondre lorsqu’elles seront lues ou écrites. Cela peut entraîner la lecture de données non valides lors de l'accès à de telles adresses ou le blocage du système.

Qu'en est-il des systèmes dotés de plus de 4 Go de RAM (par exemple: 8 Go, 16 Go, etc.)?

Pour que cela reste un peu simple: les processeurs 64 bits ont plus d'adresses (ce qui les rend 64 bits - par exemple, 0x0000000000000000 à 0xFFFFFFFFFFFFFFFF), de sorte que la RAM supplémentaire "s'adapte". En supposant que le processeur est en mode long . Jusque-là, la RAM est là, mais pas adressable.

Pourquoi la pile est-elle initialisée avec une valeur (dans ce cas, une valeur située à 0xFFFFFFF0)?

Je ne trouve rien immédiatement sur quoi x86 attribue le pointeur de pile à la mise sous tension, mais il devra éventuellement être réaffecté par une routine d'initialisation de toute façon une fois que cette routine aura découvert la quantité de RAM disponible dans le système. (@Eric Towers dans les commentaires ci-dessous indique qu'il est défini sur zéro lors de la mise sous tension.)

LawrenceC
la source
7
Il est préférable de concevoir l'espace d'adressage comme un grand espace dans lequel le matériel peut être affecté. Lorsque la CPU lit / écrit en mémoire, elle établit une communication sur un bus et le matériel peut s’assurer que des éléments tels que la RAM ou la ROM répondent à des plages d’adresses spécifiques. Donc, un tel matériel devrait s’assurer qu’une ROM répond à 0xFFFFFFF0 lors de la réinitialisation de la CPU. Il n’existe aucune obligation inhérente que ROM apparaisse juste après RAM. Il peut apparaître partout où le matériel le dit également, en fonction de ses capacités.
LawrenceC
4
Il est possible d'avoir des "trous" ou des espaces non attribués qui ne sont pas utilisés par la ROM, la RAM ou quoi que ce soit. En général, l'accès à ceux-ci provoquera un blocage du système.
LawrenceC
16
Cette réponse suppose que la CPU peut utiliser 32 bits d'adresse en mode 16 bits. Mais en mode 16 bits, il ne peut utiliser que 20 bits d’adresse. L'adresse 0xFFFFFFF0n'est accessible que lorsque la CPU est passée en mode 32 bits. La dernière fois que j'ai examiné le code du BIOS, le point d’entrée était 0xFFFF0:
Kasperd
6
@ MichaelKjörling votre calcul est faux. Le segment et le décalage décalés ne sont pas des OR, ils sont ajoutés. Ainsi, FFFF logique: FFF0 est physique (1) 0FFE0 (où 1 est présent si A20 est activé).
Ruslan
9
@kasperd Il y a un hack en place - le gestionnaire de mémoire a les 12 bits les plus hauts réglés sur 1 jusqu'à ce que le premier saut en longueur ait lieu. Donc oui, logiquement, vous travaillez avec 0xFFFF0, mais en réalité, cela correspond à 0xFFFFFFF0. Je suppose que cela a été fait pour assurer la compatibilité avec le 8086 - il semble que les processeurs, tout comme les plus modernes 0xFFFF0, l' utilisent , mais les processeurs 32 bits y ont réellement accès 0xFFFFFFF0(mappés sur la ROM du BIOS).
Luaan
26

Il n'est pas situé au sommet de la RAM; il se trouve dans une ROM dont l'adresse se situe en haut de l'espace d'adressage de la mémoire, ainsi que sur les cartes d'extension, telles que les contrôleurs Ethernet. Il est là pour éviter tout conflit avec la RAM, du moins jusqu'à ce que vous ayez 4 Go installés. Les systèmes disposant de 4 Go ou plus de RAM peuvent faire deux choses pour résoudre le conflit. Les cartes mères bon marché ignorent tout simplement les parties de la RAM en conflit avec l'emplacement de la ROM. Les décents remappent cette RAM pour donner l’apparence d’une adresse supérieure à 4 Go.

Je ne suis pas sûr de ce que vous demandez à propos de la pile. Ce n'est certainement pas initialisé pour être en ROM. Lorsque la CPU se réinitialise, elle passe initialement en "mode réel", dans laquelle elle agit comme le 8086 d'origine et utilise un adressage segmenté de 16 bits, ne lui permettant que d'accéder à 1 Mo de mémoire. Le code du BIOS est situé en haut de ce 1 Mo. Le BIOS sélectionne quelque part dans la RAM pour configurer la pile, puis charge et exécute le premier secteur du premier lecteur amorçable. Il appartient au système d'exploitation de passer en mode 32 ou 64 bits une fois qu'il prend le relais et configure ses propres piles (une par tâche / thread).

psusi
la source
1
Merci beaucoup pour la réponse, mais @LawrenceC a donné plus de détails sur sa réponse et m'a aidé à comprendre comment tout cela fonctionne. En tout cas, merci! Je vous donne un vote positif: 3
Fernando Paladini
13

Tout d’abord, cela n’a vraiment rien à voir avec la RAM. Nous parlons ici d' espace d'adressage - même si vous ne disposez que de 16 Mo de mémoire, vous disposez toujours de 32 bits d'espace d'adressage sur un processeur 32 bits.

Cela répond déjà à votre première question. En fait, au moment de sa conception, les PC du monde réel n’avaient nulle part près des 4 Go de mémoire; ils étaient plus dans la gamme de 1-16 Mio de mémoire. L'espace d'adressage était, à toutes fins pratiques, gratuit.

Maintenant, pourquoi 0xFFFFFFF0 exactement? Le processeur ne sait pas quelle quantité de BIOS il y a. Certains BIOS peuvent ne prendre que quelques kilo-octets, alors que d'autres peuvent occuper tout un mégaoctet de mémoire - et je n'entre même pas dans les différentes mémoires RAM optionnelles. Le processeur doit être câblé à une adresse quelconque pour commencer - il n'y a pas de configuration pour configurer le processeur. Mais il ne s'agit que d'un mappage de l'espace d'adressage - l'adresse est mappée directement dans la puce ROM du BIOS (oui, cela signifie que vous n'avez pas accès à la totalité des 4 Go de RAM à ce stade si vous en avez beaucoup - mais cela n’a rien de spécial, de nombreux périphériques ont besoin de leur propre plage d’adresses). Sur un processeur 32 bits, cette adresse vous donne 16 octets complets pour effectuer l’initialisation très basique - ce qui suffit pour configurer vos segments et, si nécessaire, le mode adresse (rappelez-vous,véritable démarrage "procédure". À ce stade, vous n’utilisez pas du tout de RAM, c’est juste une ROM mappée. En fait, la RAM n’est même pas prête à être utilisée à ce stade - c’est l’une des tâches du POST du BIOS! Vous vous demandez peut-être comment un mode réel de 16 bits peut accéder à l'adresse 0xFFFFFFF0? Bien sûr, il y a des segments, vous avez donc un espace d'adressage de 20 bits, mais cela ne suffit toujours pas. Eh bien, il y a une astuce: les 12 bits de poids fort de l'adresse sont définis jusqu'à ce que vous exécutiez votre premier saut en longueur, ce qui vous donne accès à l'espace d'adressage en hauteur (tout en refusant l'accès à une valeur inférieure à 0xFFF00000 - jusqu'à ce que vous exécutiez un saut en longueur) .

Tous ces éléments sont essentiellement masqués par les programmeurs (sans parler des utilisateurs) sur les systèmes d'exploitation modernes. Vous n’avez généralement accès à aucun niveau aussi bas - certaines choses sont déjà irrécupérables (vous ne pouvez pas changer de mode de processeur à tout moment), d’autres sont gérées exclusivement par le noyau du système d’exploitation.

Une vue plus agréable provient donc du codage old-school sous MS DOS. Un autre exemple typique de mémoire de périphérique mappée directement sur un espace d'adressage est l'accès direct à la mémoire vidéo. Par exemple, si vous voulez écrire rapidement du texte sur l’affichage, vous écrivez directement dans adresse B800:0000(plus décalage - en mode texte 80x25, cela signifie que (y * 80 + x) * 2si ma mémoire est fidèle - deux octets par caractère, ligne par ligne). Si vous vouliez dessiner pixel par pixel, vous utilisiez un mode graphique et l’adresse de départ de A000:0000(typiquement, 320x200 à 8 bits par pixel). Faire quelque chose de très performant signifiait généralement plonger dans les manuels des appareils pour savoir comment y accéder directement.

Cela survit à ce jour - c'est juste caché. Sous Windows, vous pouvez voir les adresses de mémoire mappées aux périphériques dans le Gestionnaire de périphériques. Ouvrez simplement les propriétés de votre carte réseau, allez à l'onglet Ressources. Tous les éléments de la plage de mémoire sont des mappages de la mémoire du périphérique vers votre espace d'adressage principal. Et sur 32 bits, vous verrez que la plupart de ces périphériques sont mappés au-dessus de la marque 2 GiB (plus tard 3 GiB) - encore une fois, pour réduire les conflits avec la mémoire utilisable par l'utilisateur, bien que cela ne soit pas vraiment un problème avec la mémoire virtuelle ( les applications ne s'approchent pas de l' espace d'adressage matériel réel - elles ont leur propre bloc de mémoire virtualisé, qui peut être mappé sur la RAM, la ROM, les périphériques ou le fichier de page, par exemple).

Pour ce qui est de la pile, cela devrait aider à comprendre que, par défaut, la pile se développe à partir du haut. Donc, si vous faites un push, le nouveau pointeur de pile sera 0xFFFFFEC: autrement dit, vous n'essayez pas d'écrire sur l'adresse d'initialisation du BIOS :) Cela signifie bien sûr que les routines d'initialisation du BIOS peuvent utiliser la pile en toute sécurité, avant de la remapper. quelque part plus utile. Dans la programmation traditionnelle, avant que la pagination ne devienne la valeur par défaut, la pile commençait généralement à la fin de la mémoire vive et un "débordement de pile" se produisait lorsque vous commenciez à écraser la mémoire de votre application. La protection de la mémoire a beaucoup changé, mais en général, elle maintient la compatibilité avec les versions antérieures autant que possible. Notez que même le processeur x86-64 le plus moderne peut toujours démarrer MS DOS 5. - ou comment Windows peut toujours exécuter de nombreuses applications DOS qui n'ont aucune idée de la pagination.

Luaan
la source
3
Excellente réponse, juste pour développer et dire que les processeurs modernes commencent à se débarrasser de hacks comme le masquage de ligne A20 , de sorte que la prise en charge des cas marginaux plus anciens est en train de disparaître.
Basic
2
Jusqu'au dernier paragraphe: Le BIOS ne peut pas utiliser la pile "librement": il ne peut pas écrire dans la ROM (sur laquelle 0xFFFFFFECserait mappé). Cela signifie non seulement non pushmais par exemple non callplus. Ceux-ci doivent attendre que la RAM soit prête.
Le Vee
7

En plus des autres points mentionnés, il peut être utile de comprendre ce qu'est une adresse est . Tandis que les architectures récentes compliquent les choses, une machine publiait à chaque cycle de mémoire l’adresse désirée sur 20 à 32 fils (selon l’architecture, avec quelques astuces spéciales pour noter si elle nécessitait une paire ou quatre octets simultanément); diverses parties du système de mémoire examineraient l'état de ces fils et s'activeraient lorsqu'elles verraient certaines combinaisons de valeurs hautes et basses.

Si une machine dotée de 32 câbles d’adresse ne devait utiliser que 1 Mo de RAM et 64 Ko de ROM [assez plausible pour certains contrôleurs intégrés], elle pourrait activer la RAM pour toutes les adresses où le fil d’adresse supérieur était bas et la ROM pour toutes les adresses où il se trouvait. haute. Les 20 fils d’adresse du bas seraient alors liés à la RAM pour sélectionner l’un des 1 048 576 octets et les 16 derniers seraient également connectés à la ROM, pour choisir l’un des 65 536 octets. Les 11 fils d’adresse restants ne seraient tout simplement pas connectés à quoi que ce soit.

Sur une telle machine, les accès aux adresses 0x00100000-0x001FFFFF seraient équivalents aux accès aux adresses RAM 0x00000000-0x000FFFFF. De même avec les adresses 0x000200000-0x0002FFFFF ou 0x7FF00000-0x7FFFFFFFF. Les adresses supérieures à 0x80000000 liraient toutes en ROM, avec un motif de 64 Ko répété dans tout l'espace.

Bien que le processeur dispose d'un espace d'adressage de 4 294 967 296 octets, il n'est pas nécessaire que le matériel reconnaisse autant d'adresses différentes. Placer le vecteur de réinitialisation près du haut de l'espace d'adressage est une conception qui fonctionnera bien quelle que soit la quantité de mémoire RAM et de ROM dont dispose le système et évite la nécessité de décoder complètement l'espace d'adressage.

supercat
la source
Bon point - Vous ne trouverez pas de matériel 64 bits prenant en charge quoi que ce soit près de l’espace mémoire adressable 64 bits (ou même 1x10 ^ -12 de celui-ci).
Basic
3

Mon cas est parce que nous utilisons la logique négative, le numérique (1) n’existe aucune tension (0 volts). Il suffit de mettre les 4 derniers bits sous tension lors de l’initialisation pour que le compteur de programme (ou le pointeur d’instruction) se mette à 1111 1111 1111 1111 1111 1111 1111 0000. Nous n'avons pas à nous adresser aux 28 bits supérieurs, car la plupart des processeurs (anciens) avaient 16 bits et les nœuds inférieurs pouvaient être adressés par une seule puce d'adresse auparavant. Maintenant que nous avons 64 bits avec une compatibilité de 32 bits et de 32 bits à 16 bits, la méthode matérielle a été améliorée mais la méthode est restée inchangée. De plus, les bioses ne sont pas toujours programmées sur 64 ou 32 bits. Mon opinion est également puisque les souvenirs ne sont pas toujours les mêmes, le bios doit être situé sur le même segment. La façon dont nous abordons le bios n’est pas la vraie adresse tout le temps. Juste un appris de moi ...

Agguro
la source
2

Lors de la réinitialisation, un processeur compatible 8088/8086 exécute les instructions à 0FFFF0, soit 16 octets sous la limite de 1 mégaoctet. normalement la ROM à cet emplacement (dans les implémentations de PC) serait le BIOS, donc à la fin de la ROM du BIOS, il y a un saut au début de la ROM du BIOS.

montré ici: vecteur de départ et signature 'date' derrière, BIOS 5150 d'IBM 5150 PC 8KB date du: 19/10/1981

00001FEE  FF                db 0xff
00001FEF  FF                db 0xff
00001FF0  EA5BE000F0        jmp word 0xf000:0xe05b
00001FF5  3130              xor [bx+si],si
00001FF7  2F                das
00001FF8  3139              xor [bx+di],di

notez que l'adressage est d'une valeur de 8KB $ 2000 rom, qui place l'adresse de départ (le JMP absolu, à n'importe quel autre emplacement, dans ce cas dans la même quantité de 8KB, bien que ce ne soit pas l'adresse la plus basse possible): $ FFFF: Segmenté à 0 $ ou linéaire FFFF0.

en ce qui concerne la compatibilité: si un processeur "futur" ou actuel "s'attend" à ce qu'il ait beaucoup plus de F devant l'adresse, cela n'a pas d'importance. pour la compatibilité des processeurs les plus récents dans les systèmes plus anciens, les lignes d’adresse supplémentaires ne sont pas connectées et, par conséquent, les données sur le bus de données sont exactement les mêmes. tant que les bits les moins significatifs restent FFFF0.

(Dans un système avec seulement 1 Mo de RAM et la ROM située à la fin de celui-ci, rien de plus, il sera heureux de penser qu'il parle à l'adresse la plus élevée tout en obtenant exactement les mêmes données, car ces implémentations n'ont jamais entendu parler de lignes d'adresse supérieures à A19)

notez que le monde n’est pas que des "ordinateurs" ... l’ordinateur IBM était un "accident", ces processeurs n’ont jamais été conçus spécifiquement pour les "ordinateurs" et constituent bien plus que de simples ordinateurs (tels que systèmes d'armes, etc.). Les modes protégés 32 et 64 bits ne sont généralement pas souhaités. (Le mode virtuel 8086 est beaucoup plus intéressant en tant que raison de choisir une version plus récente (386+) par exemple). par conséquent, la «compatibilité ascendante» comporte bien plus que la simple exécution.

SAR Sven Olaf von CyberBunker
la source
1

La carte mère veille à ce que l'instruction du vecteur de réinitialisation corresponde à un saut vers l'emplacement de mémoire mappé sur le point d'entrée du BIOS. Ce saut efface implicitement l'adresse de base cachée présente à la mise sous tension. Grâce à la carte mémoire conservée par le chipset, tous les emplacements de mémoire disposent du contenu adéquat requis par la CPU. Ils sont tous mappés sur une mémoire flash contenant le BIOS car, à ce stade, les modules de RAM ont une merde aléatoire.

viktorkh
la source