Comment l'ALU dans un microprocesseur ferait-il la différence entre un nombre signé, -7 qui est désigné par 1111 et un nombre non signé 15, également désigné par 1111?
Comment l'ALU dans un microprocesseur ferait-il la différence entre un nombre signé, -7 qui est désigné par 1111 et un nombre non signé 15, également désigné par 1111?
Réponses:
La réponse courte et simple est: ce n'est pas le cas. Aucun processeur ISA grand public moderne ne fonctionne comme vous le pensez.
Pour le CPU, c'est juste un motif de bits. C'est à vous, le programmeur, de garder une trace de ce que signifie ce modèle de bits.
En général, les ISA ne font pas de distinction entre les différents types de données en matière de stockage. (Ignorer les registres à usage spécial tels que les registres flottants dans une FPU.) Ce n'est qu'un modèle insignifiant de bits vers le CPU. Cependant, les normes ISA n'ont différents types d'instructions qui peuvent interpréter le motif de bits de différentes façons. Par exemple, des instructions arithmétiques telles que , , , interprètent le modèle binaire comme une sorte de nombre, alors que des instructions logiques telles que , , l' interpréter comme un tableau de booléens. Ainsi, c'est au programmeur (ou à l'auteur de l'interpréteur ou du compilateur si vous utilisez un langage de niveau supérieur) de choisir les bonnes instructions.MUL
DIV
ADD
SUB
AND
OR
XOR
Il peut très bien y avoir des instructions distinctes pour les numéros signés et non signés, par exemple. Certaines ISA ont également des instructions pour l'arithmétique avec des décimales codées binaires.
Cependant, notez que j'ai écrit "ISA grand public moderne" ci-dessus. Il existe en fait des normes ISA non traditionnelles ou historiques qui fonctionnent différemment. Par exemple, l'ISA CISC 48 bits d'origine d'IBM AS / 400 ainsi que l'ISA RISC 64 bits actuel du système désormais appelé IBM i, distinguent les pointeurs des autres valeurs. Les pointeurs sont toujours balisés et incluent les informations de type et la gestion des droits. Le CPU sait si une valeur est un pointeur ou non, et seul le noyau i / OS privilégié est autorisé à manipuler librement les pointeurs. Les applications utilisateur ne peuvent manipuler les pointeurs qu'elles possèdent que pour pointer vers la mémoire qu'elles possèdent en utilisant un petit nombre d'instructions sûres.
Il y avait également des conceptions ISA historiques qui incluaient au moins une forme limitée de connaissance du type.
char
, qui est un type non signé 16 bits. Bien sûr, il n'y a toujours pas d'instructions arithmétiques non signées dans le bytecode Java, car toutes les char
valeurs sont automatiquement promues int
(signées 32 bits) pour l'arithmétique.
Version courte: il ne sait pas. Il n'y a aucun moyen de le savoir.
Si 1111
représente -7, alors vous avez une représentation de la magnitude du signe , où le premier bit est le signe et le reste des bits est la magnitude. Dans ce cas, l'arithmétique est quelque peu compliquée, car un ajout non signé et un ajout signé utilisent une logique différente. Donc, vous auriez probablement un SADD
et un UADD
opcode, et si vous choisissez le mauvais, vous obtenez des résultats absurdes.
Le plus souvent, cependant, 1111
représente -1, dans ce qu'on appelle une représentation à deux compléments . Dans ce cas, l'ALU ne se soucie simplement pas que les numéros soient signés ou non! Par exemple, prenons l'opération de 1110 + 0001
. En arithmétique signée, cela signifie "-2 + 1", et le résultat devrait être -1 ( 1111
). En arithmétique non signée, cela signifie "14 + 1", et le résultat devrait être 15 (1111
). Donc, l'ALU ne sait pas si vous voulez un résultat signé ou non signé, et il s'en fiche. Il fait simplement l'ajout comme s'il n'était pas signé, et si vous souhaitez le traiter comme un entier signé par la suite, c'est à vous de décider.
EDIT: Comme Ruslan et Daniel Schepler le soulignent à juste titre dans les commentaires, certains opérandes ont encore besoin de versions distinctes signées et non signées, même sur une machine à deux. L'addition, la soustraction, la multiplication, l'égalité et tout cela fonctionne bien sans savoir si les nombres sont signés ou non. Mais la division et toute comparaison supérieure / inférieure doivent avoir des versions distinctes.
EDIT EDIT: Il y a aussi d'autres représentations, comme son complément , mais celles-ci ne sont plus utilisées, donc vous ne devriez pas avoir à vous en soucier.
<
<=
>=
>
sont différents pour les opérandes signés par rapport aux opérandes non signés ==
et !=
sont indépendants de la signature.
L'un des grands avantages des mathématiques à complément à deux, que toutes les architectures modernes utilisent, est que les instructions d'addition et de soustraction sont exactement les mêmes pour les opérandes signés et non signés.
De nombreux processeurs n'ont même pas d'instructions de multiplication, de division ou de module. S'ils le font, ils doivent avoir des formes distinctes signées et non signées de l'instruction, et le compilateur (ou le programmeur en langage assembleur) choisit celle appropriée.
Les processeurs ont également généralement des instructions différentes pour les comparaisons signées ou non signées. Par exemple, x86 peut suivre un CMP
avec JL
(Aller si moins que) si la comparaison doit être signée, ou JB
(Aller si ci-dessous) si la comparaison doit être non signée. Encore une fois, le compilateur ou le programmeur choisirait la bonne instruction pour le type de données.
Quelques autres instructions viennent souvent dans des variantes signées et non signées, telles que le décalage à droite ou le chargement d'une valeur dans un registre plus large, avec ou sans extension de signe.
smulh
et umulh
qui ne renvoient que les bits supérieurs de la multiplication et les instructions signées et non signées qui renvoie le résultat dans un registre deux fois plus large que les opérandes source.
Ce n'est pas le cas. Le processeur s'appuie sur le jeu d'instructions pour lui dire quel type de données il regarde et où les envoyer. Il n'y a rien à propos des 1 et des 0 dans l'opérande lui-même qui peut intrinsèquement signaler à l'ALU si les données sont un caractère, un flottant, un entier, un entier signé, etc. Si ce 1111 va sur un circuit électrique qui attend un complément de 2 secondes, ça va à interpréter comme un complément à 2s.
char
niveau matériel. Peut-être une fois, à l'époque des téléimprimeurs mécaniques. Mais aujourd'hui, un char
est tout simplement un certain nombre dans la mesure où le matériel est concerné. La raison pour laquelle différents nombres correspondent à différentes formes de lettres sur votre écran est que ces nombres sont utilisés pour sélectionner différents bitmaps ou différentes routines de dessin à partir d'un grand tableau (c'est-à-dire à partir d'une "police").
Je voudrais apporter un complément aux réponses déjà apportées:
Dans la plupart des autres réponses, il est noté que dans l'arithmétique à deux compléments, le résultat est le même pour les nombres signés et non signés:
-2 + 1 = -1 1110 + 0001 = 1111
14 + 1 = 15 1110 + 0001 = 1111
Cependant , il existe des exceptions:
Division:
-2 / 2 = -1 1110 / 0010 = 1111
14 / 2 = 7 1110 / 0010 = 0111
Comparison:
-2 < 2 = TRUE 1110 < 0010 = TRUE
14 < 2 = FALSE 1110 < 0010 = FALSE
"Typical" (*) multiplication:
-2 * 2 = -4 1110 * 0010 = 11111100
14 * 2 = 28 1110 * 0010 = 00011100
(*) Sur de nombreux processeurs, le résultat d'une multiplication de deux nombres à n bits a une largeur de (2 * n) bits.
Pour de telles opérations, les CPU ont des instructions différentes pour l'arithmétique signée et non signée.
Cela signifie que le programmeur (ou le compilateur) doit utiliser d'autres instructions pour l'arithmétique signée et non signée.
Le CPU x86 par exemple a une instruction nommée div
pour faire une division non signée et une instruction nommée idiv
pour faire une division signée.
Il existe également différentes instructions "conditionnelles" (sauts conditionnels, set-bit-on-condition) ainsi que des instructions de multiplication pour l'arithmétique signée et non signée.