Как ALU в микропроцессоре различает число со знаком -7, обозначаемое 1111, и число без знака 15, обозначаемое также 1111?
Как ALU в микропроцессоре различает число со знаком -7, обозначаемое 1111, и число без знака 15, обозначаемое также 1111?
Ответы:
Короткий и простой ответ: это не так. Ни один современный процессор ISA не работает так, как вы думаете.
Для процессора это всего лишь небольшая схема. Вы, программист, должны следить за тем, что означает этот битовый шаблон.
В целом, ISA не различают разные типы данных, когда речь идет о хранилище. (Игнорирование регистров специального назначения, таких как плавающие регистры в FPU.) Это просто бессмысленный набор битов для CPU. Тем не менее, ИСАС делать разные виды инструкций , которые могут интерпретировать битовую комбинацию по - разному. Например, арифметические команды , такие как MUL
, DIV
, ADD
, SUB
интерпретировать битовый шаблон в качестве какого - то числа, в то время как логические команды , таких как AND
, OR
, XOR
интерпретировать его как массив логических значений. Таким образом, программист (или автор интерпретатора или компилятора, если вы используете язык более высокого уровня) должен выбрать правильные инструкции.
Например, могут быть отдельные инструкции для чисел со знаком и без знака. Некоторые ISA также имеют инструкции по арифметике с двоично-десятичными знаками.
Тем не менее, обратите внимание, что я написал «современный основной ISA» выше. На самом деле существуют неосновные или исторические ISA, которые работают по-другому. Например, как исходная 48-разрядная CISC ISA в IBM AS / 400, так и текущая 64-разрядная RISC ISA на базе POWER системы, которая теперь называется IBM i, различают указатели и другие значения. Указатели всегда помечены и включают информацию о типе и управление правами. Процессор знает, является ли значение указателем или нет, и только привилегированное ядро i / OS может свободно манипулировать указателями. Пользовательские приложения могут манипулировать только указателями, которые им принадлежат, чтобы указывать на свою память, используя небольшое количество безопасных инструкций.
Были также некоторые исторические проекты ISA, которые включали, по крайней мере, некоторую ограниченную форму понимания типа.
char
, что является 16-битным типом. Конечно, в байт-коде Java до сих пор нет беззнаковых арифметических инструкций, поскольку любые char
значения автоматически повышаются до int
(32-разрядного со знаком) для арифметики.
Короткая версия: он не знает. Там нет никакого способа сказать.
Если 1111
представляет -7, то у вас есть представление величины знака , где первый бит является знаком, а остальные биты являются величиной. В этом случае арифметика несколько усложняется, так как при добавлении без знака и при добавлении со знаком используется другая логика. Таким образом, у вас, вероятно, есть код операции SADD
и UADD
код, и если вы выберете неправильный код, вы получите бессмысленные результаты.
Чаще, тем не менее, 1111
представляет -1, в том, что называется представлением с двумя дополнениями . В этом случае ALU просто не волнует, подписаны ли числа или нет! Например, давайте возьмем операцию 1110 + 0001
. В знаковой арифметике это означает «-2 + 1», и результат должен быть -1 ( 1111
). В арифметике без знака это означает «14 + 1», и результат должен быть 15 ( 1111
). Таким образом, ALU не знает, хотите ли вы получить подписанный или неподписанный результат, и ему все равно. Он просто добавляет сложение так, как если бы оно было беззнаковым, и если вы хотите потом рассматривать это как целое число со знаком, это ваше дело.
РЕДАКТИРОВАТЬ: Как справедливо указывают Руслан и Даниэль Шеплер в комментариях, некоторые операнды все еще нуждаются в отдельных версиях с подписью и без знака, даже на машине с двумя дополнениями. Сложение, вычитание, умножение, равенство и т. Д. Все прекрасно работает, не зная, подписаны числа или нет. Но деление и любые сравнения больше / меньше чем должны иметь разные версии.
РЕДАКТИРОВАТЬ РЕДАКТИРОВАТЬ: Существуют и другие представления, например, дополнения , но в основном они больше никогда не используются, поэтому вам не нужно беспокоиться о них.
<
<=
>=
>
различаются для операндов ==
со !=
знаком и без знака, тогда как и являются независимыми от подписи.
Одно из больших преимуществ математики с двумя дополнениями, которую используют все современные архитектуры, состоит в том, что инструкции сложения и вычитания одинаковы для операндов со знаком и без знака.
Многие процессоры даже не имеют команд умножения, деления или модуля. Если это так, у них должны быть отдельные подписанные и неподписанные формы инструкции, и компилятор (или программист на языке ассемблера) выбирает соответствующую.
Процессоры также обычно имеют разные инструкции для сравнения со знаком или без знака. Например, x86 может следовать CMP
с JL
(Перейти, если меньше чем), если сравнение должно быть подписано, или JB
(Перейти, если ниже), если сравнение должно быть без знака. Опять же, компилятор или программист выберет правильную инструкцию для типа данных.
Несколько других инструкций часто бывают в знаковых и беззнаковых вариантах, таких как сдвиг вправо или загрузка значения в более широкий регистр, с расширением знака или без него.
smulh
и umulh
которые возвращают только верхние биты умножения , а также инструкции со знаком и без знака, которые вернуть результат в регистр в два раза шире, чем исходные операнды.
Это не так. Процессор полагается на набор инструкций, чтобы сообщить ему, на какой тип данных он смотрит и куда его отправлять. В самом операнде нет ничего о единицах и 0, которые по своей сути могли бы сигнализировать ALU, являются ли данные символами, числами с плавающей запятой, int, со знаком int и т. Д. Если этот 1111 собирается в электрическую цепь, ожидающую дополнения 2 с, он собирается быть интерпретированным как дополнение 2s.
char
на аппаратном уровне. Может быть, когда-то давно, во времена механических телепринтеров. Но сегодня аппаратное обеспечение - char
это просто число. Причина того, что разные цифры соответствуют разным буквенным формам на экране, заключается в том, что эти цифры используются для выбора разных растровых изображений или разных процедур рисования из большой таблицы (т. Е. Из «шрифта»).
Я хотел бы добавить дополнение к уже сделанным ответам:
В большинстве других ответов отмечается, что в арифметике с двумя дополнениями результат одинаков для чисел со знаком и без знака:
-2 + 1 = -1 1110 + 0001 = 1111
14 + 1 = 15 1110 + 0001 = 1111
Однако есть исключения:
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
(*) На многих процессорах результат умножения двух n-битных чисел имеет ширину (2 * n) битов.
Для таких операций процессоры имеют разные инструкции для знаковой и беззнаковой арифметики.
Это означает, что программист (или компилятор) должен использовать другие инструкции для арифметики со знаком и без знака.
Например, в процессоре x86 есть инструкция, названная div
для деления без знака, и инструкция, названная idiv
для деления со знаком.
Существуют также различные «условные» инструкции (условные переходы, set-bit-on-condition), а также инструкции умножения для арифметики со знаком и без знака.