La majeure partie du contenu de cette réponse provient à l'origine de cette réponse (écrite avant que l'autre question ne soit marquée comme un double). Je parle donc d'utiliser des valeurs de 8 bits (même si cette question portait sur des valeurs de 32 bits), mais cela ne pose pas de problème car les valeurs de 8 bits sont plus simples à comprendre sur le plan conceptuel, et les mêmes concepts s'appliquent à des valeurs plus importantes comme l'arithmétique de 32 bits.
Lorsque vous ajoutez deux nombres de 8 bits, vous obtenez le plus grand nombre possible (0xFF + 0xFF = 1FE). En fait, si vous multipliez deux nombres de 8 bits, le plus grand nombre que vous pouvez obtenir (0xFF * 0xFF = 0xFE01) est toujours de 16 bits, soit deux fois 8 bits.
Maintenant, vous pouvez supposer qu'un processeur x-bit ne peut suivre que des x-bits. (Par exemple, un processeur 8 bits ne peut suivre que 8 bits.) Ce n'est pas exact. Le processeur 8 bits reçoit les données en morceaux de 8 bits (ces “morceaux” ont généralement un terme formel : un “mot”). Sur un processeur 8 bits, des mots de 8 bits sont utilisés. Sur un processeur 64 bits, des mots de 64 bits peuvent être utilisés).)
Donc, lorsque vous donnez à l'ordinateur 3 octets :
Octet #1 : l'instruction MUL
Octet #2 : les octets d'ordre supérieur (par exemple, 0xA5)
Octet #3 : les octets d'ordre inférieur (par exemple, 0xCB)
L'ordinateur peut générer un résultat qui est supérieur à 8 bits. L'unité centrale peut générer des résultats comme ceci :
0100 0000 0100 0010 xxxx xxxx xxxx xxxx 1101 0111
alias :
0x4082xxxxD7
Maintenant, laissez-moi interpréter cela pour vous :
0x signifie simplement que les chiffres suivants sont hexadécimaux.
Je parlerai du “40” plus en détail dans un instant.
82 fait partie du registre “A”, qui est une série de 8 bits.
xx et xx font partie de deux autres registres, appelés registre “B” et registre “C”. La raison pour laquelle je n'ai pas rempli ces bits avec des zéros ou des uns est qu'une instruction “ADD” (envoyée à l'unité centrale) peut faire en sorte que ces bits soient inchangés par l'instruction (alors que la plupart des autres bits que j'utilise dans cet exemple peuvent être altérés, à l'exception de certains des bits de drapeau).
D7 rentrerait dans plus de bits, appelés le registre “D”.
Un registre est juste un morceau de mémoire. Les registres sont intégrés dans les unités centrales, de sorte que l'unité centrale peut accéder aux registres sans avoir besoin d'interagir avec la mémoire sur une clé USB.
Donc le résultat mathématique de 0xA5 fois 0xCB est 0x82D7.
Maintenant, pourquoi les bits ont-ils été divisés en registres A et D au lieu des registres A et B, ou des registres C et D ? Eh bien, encore une fois, c'est un exemple de scénario que j'utilise, dont le concept est assez similaire à un vrai langage assembleur (Intel x86 16 bits, tel qu'utilisé par les Intel 8080 et 8088 et de nombreux CPU plus récents). Il pourrait y avoir quelques règles communes, telles que le registre “C” utilisé comme index pour compter les opérations (typique pour les boucles), et le registre “B” utilisé pour garder une trace des décalages qui aident à spécifier les emplacements de mémoire. Ainsi, “A” et “D” peuvent être plus courants pour certaines des fonctions arithmétiques communes.
Chaque instruction du CPU devrait avoir une certaine documentation, utilisée par les personnes qui programment en assembleur. Cette documentation devrait spécifier quels registres sont utilisés par chaque instruction. (Ainsi, le choix des registres à utiliser est souvent spécifié par les concepteurs de l'unité centrale, et non par les programmeurs en langage assembleur. Bien qu'il puisse y avoir une certaine flexibilité).
Maintenant, revenons au “40” dans l'exemple ci-dessus : c'est une série de bits, souvent appelée “registre flags”. Chaque bit du registre des drapeaux a un nom. Par exemple, il y a un bit de “débordement” que le CPU peut définir si le résultat est plus grand que l'espace qui peut stocker un octet des résultats. (Le bit de “débordement” peut souvent être désigné par le nom abrégé “OF”. C'est un “o” majuscule, pas un zéro). Un logiciel peut vérifier la valeur de ce drapeau et noter le “problème”. Le travail avec ce bit est souvent géré de manière invisible par des langages de niveau supérieur, de sorte que les programmeurs débutants n'apprennent souvent pas comment interagir avec les drapeaux du CPU. Cependant, les programmeurs en assembleur peuvent généralement accéder à certains de ces drapeaux d'une manière très similaire à d'autres variables.
Par exemple, vous pouvez avoir plusieurs instructions ADD. Une instruction ADD peut stocker 16 bits de résultats dans le registre A et le registre D, tandis qu'une autre instruction peut simplement stocker les 8 bits de poids faible dans le registre A, ignorer le registre D et spécifier le bit de débordement. Ensuite, plus tard (après avoir stocké les résultats du registre A dans la mémoire vive principale), vous pouvez utiliser une autre instruction ADD qui ne stocke que les 8 bits de poids fort dans un registre (éventuellement le registre A.) La nécessité d'utiliser un drapeau de débordement peut dépendre de l'instruction de multiplication utilisée. La nécessité d'utiliser un indicateur de débordement peut dépendre de l'instruction de multiplication que vous utilisez. (Il y a aussi généralement un indicateur de “sous-débordement”, au cas où vous soustrairez trop de données pour obtenir le résultat souhaité). Juste pour vous montrer à quel point les choses sont devenues compliquées :
L'Intel 4004 était un processeur 4 bits
L'Intel 8008 était un processeur 8 bits. Il avait des registres de 8 bits nommés A, B, C et D.
L'Intel 8086 était un CPU de 16 bits. Il avait des registres de 16 bits nommés AX, BX, CX et DX.
L'Intel 80386 était un processeur 32 bits. Il avait des registres 32 bits nommés EAX, EBX, ECX et EDX.
Les processeurs Intel x64 ont des registres 64 bits nommés RAX, RBX, RCX et RDX. Les puces x64 peuvent exécuter un code 16 bits (dans certains modes de fonctionnement) et peuvent interpréter des instructions 16 bits. Ce faisant, les bits qui composent le registre AX sont la moitié des bits qui composent le registre EAX, qui sont la moitié des bits qui composent le registre RAX. Ainsi, chaque fois que vous changez la valeur de AX, vous changez également EAX et RAX, car ces bits utilisés par AX font partie des bits utilisés par RAX. (Si vous changez EAX par une valeur qui est un multiple de 65 536, alors les 16 bits inférieurs sont inchangés, donc AX ne changera pas. Si vous changez EAX par une valeur qui n'est pas un multiple de 65 536, alors cela affectera également AX)
Il y a plus de drapeaux et de registres que ceux que j'ai mentionnés. J'ai simplement choisi quelques uns des plus utilisés pour fournir un exemple conceptuel simple.
Maintenant, si vous êtes sur un CPU 8 bits, lorsque vous écrivez en mémoire, vous pouvez trouver quelques restrictions concernant la possibilité de se référer à une adresse de 8 bits, et non pas à une adresse de 4 bits ou 16 bits. Les détails varieront en fonction du CPU, mais si vous avez de telles restrictions, il se peut que le CPU traite des mots de 8 bits, c'est pourquoi le CPU est le plus souvent appelé “CPU 8 bits”.