Как CPU вычитает

У меня есть некоторые основные сомнения, но каждый раз, когда я сижу, чтобы попробовать свои руки на собеседовании, эти вопросы и мои сомнения появляются.

Скажите A = 5

В = -2

Я говорю A + B. Я предполагаю, что A и B являются 4-байтами Как CPU делает это дополнение? Я понимаю, что A будет иметь знаковый бит (MSB) как 0, чтобы обозначить положительное целое число и B будет иметь знак бит как 1, чтобы обозначить отрицательное целое число.

Теперь, когда в программе на С++ я хочу распечатать A + B, модуль добавления ALU (Арифметический логический блок) сначала проверяет бит знака, а затем решает сделать вычитание, а затем следовать процедуре вычитания. Как вычитание будет сделано, будет мой следующий вопрос.

А = 5

В = 2

хочу сделать A-B компьютер возьмет 2-секундное дополнение к B и добавит дополнение A + 2s и вернет его (после отбрасывания дополнительного бита слева)?

А = 2

В = 5

сделать A-B Как компьютер в этом случае?

Я понимаю, что любая условная логика if-then и т.д. будет выполняться в аппаратном обеспечении внутри ALU. компьютерное дополнение 2s и т.д., отбрасывание дополнительного бита будет выполняться в аппаратном обеспечении внутри ALU. Как выглядит этот компонент ALU?

Спасибо,

4 ответа

Вся причина, по которой мы используем 2's-дополнение, заключается в том, что добавление одинаково, являются ли цифры положительными или отрицательными - особых случаев для рассмотрим, как есть 1's-supplement или signed-magn представления.

Итак, чтобы найти A-B, мы можем просто отрицать B и добавить; т.е. находим A + (-B), а потому, что мы используем 2'-дополнение, мы не волнуемся, если (-B) положительно или отрицательно, потому что алгоритм сложения работает одинаково в любом случае.


Подумайте в терминах двух или трех бит, а затем поймите, что эти вещи масштабируются до 32 или 64 или любых других бит.

Сначала начнем с десятичной

99
+22
===

Чтобы сделать это, у нас будет несколько "Перенести".

11
 99
+22
===
121

9 плюс 2 - 1, один, 1 плюс 9 плюс 2 - 2, один...

Дело в том, что, заметив, что для добавления двух чисел мне действительно нужны три строки, по крайней мере для некоторых из них мне может потребоваться добавить три числа. То же самое и с сумматором в alu, каждый столбец или бит-полоса, однобитовый сумматор, должен иметь возможность добавлять два входа плюс бит переноса, а результат - один бит и один бит нести.

Поскольку вы использовали 5 и 2, вы можете сделать 4 битную двоичную математику

0101
+0010
=====
 0111

Нам не нужно было переносить этот, но вы можете видеть, что работала математика, 5 + 2 = 7.

И если мы хотим добавить 5 и -2

11
 0101
+1110
=====
 0011

И ответ будет 3, как ожидалось, не удивительно, но у нас было выполнение. И так как это было добавление с минус-цифрой в двух дополнениях, все это сработало, не было бита знака, а затем добавлено два дополнения, поэтому нам не нужно просто кормить сумку двумя операндами.

Теперь, если вы хотите сделать небольшую разницу, что, если вы хотите вычесть 2 из 5, вы выбираете команду вычитания, а не добавляете. Ну, мы все узнали, что отрицание в двойном дополнении означает инвертирование и добавление одного. И мы увидели выше, что двум входным сумматорам действительно нужен третий вход для переноса, чтобы он мог быть каскадным, насколько бы широким не был сумматор. Поэтому вместо того, чтобы делать две операции добавления, инвертируйте и добавьте 1, являясь первым добавлением реального добавления, все, что нам нужно сделать, это инвертировать и установить перенос:

Поймите, что нет логики вычитания, она добавляет отрицательный результат того, что вы его кормите.

v this bit is normally zero, for a subtract we set this carry in bit
11 11
 0101 five
+1101 ones complement of 2
=====
 0011

И что вы знаете, мы получаем тот же ответ... Не имеет значения, каковы фактические значения для любого из операндов. если это операция добавления, вы ставите ноль на бит переноса и подаете его в сумматор. Если это операция вычитания, вы инвертируете второй операнд и кладете один на перенос и подаете его на тот же сумматор. Все, что выпадает, выпадает. Если ваша логика имеет достаточное количество бит для хранения результата, то все это работает, если у вас недостаточно места, тогда вы переполняете.

Существует два вида переполнения, неподписанных и подписанных. Беззнаковое - это просто бит переноса. Подписанное переполнение связано со сравнением бит переноса в столбце msbit с битом выполнения для этого столбца. Для нашей математики выше вы видите, что перенос и перенос этой колонки msbit одинаковый, оба являются одним. И нам известно, что в 4-битной системе достаточно места для правильного представления чисел +5, -2 и +3. 4-битовая система может отображать цифры +7 до -8. Поэтому, если вам нужно добавить 5 и 5 или -6 и -3, вы получите подписанное переполнение.

01 1
 0101
+0101
=====
 1010

Поймите, что логика добавления SAME используется для подписанной и неподписанной математики, это зависит от вашего кода, а не от логики, чтобы фактически определить, считались ли эти биты двумя дополнениями или без знака.

В приведенном выше примере 5 + 5 вы видите, что перенос в столбце msbit равен 1, но выполнение равно 0, что означает, что флаг V, флаг подписанного переполнения, будет установлен логикой. В то же время выполнение этого бита, который является флагом C, флаг переноса не будет установлен. Когда мышление без знака 4 бита может содержать цифры от 0 до 15, поэтому 5 + 5 = 10 не переполняется. Но когда мышление, подписанное 4 битами, может содержать от +7 до -8, а 5 + 5 = 10 - это переполнение с подписью, поэтому установлен флаг V.

если/когда у вас есть команда add with carry, они принимают схему SAME с суммированием, и вместо того, чтобы подавать перенос в ноль, он получает флаг переноса. Аналогично, вычитание с заимствованием вместо того, чтобы подавать перенос в 1, имеет значение 1 или 0 на основании состояния флага переноса в регистре состояния.

Умножение - это целая другая история, двоичный код делает умножение намного проще, чем когда он выполняется с десятичной математикой, но вы должны иметь разные инструкции без указания знака и подписки. И разделение - это отдельный отдельный зверь, поэтому большинство наборов инструкций не имеют разрыва. Многие из них не имеют размножения из-за количества окон или часов, которые он сжигает.


Вы ошибаетесь в части знакового бита. Это не просто бит знака - каждое отрицательное число преобразуется в 2 дополнения. Если вы пишете: B = -2 Компилятор при компиляции в двоичный файл сделает это: 1111 1111 1111 1111 1111 1111 1111 1110 Теперь, когда он хочет добавить 5, ALU получает 2 числа и добавляет их, простое дополнение. Когда ALU получает команду для вычитания, ему присваиваются 2 числа - он делает НЕ для каждого бита второго числа и делает простое добавление и добавляет еще 1 (потому что 2 дополнения НЕ к каждому биту +1).

Основная вещь здесь, чтобы помнить, состоит в том, что 2 дополнения были выбраны именно для того, чтобы не делать 2 отдельных процедуры для 2 + 3 и для 2 + (- 3).


В записи 2-го дополнения: не B = -B -1 или -B = (не B) + 1. Его можно проверить на компьютере или на бумаге.

Итак, A - B = A + (не B) + 1, который может быть выполнен с помощью:

1 побитовое не

1 приращение

1 дополнение

Там есть трюк, чтобы неэффективно увеличивать и уменьшать, используя только nots и отрицания. Например, если вы начинаете с номера 0 в регистре и выполняете:

нет, neg, not, neg, not, neg,... регистр будет иметь значения:

-1, 1, -2, 2, -3, 3,...

Или как еще две формулы:

not (-A) = A - 1

- (не A) = A + 1

licensed under cc by-sa 3.0 with attribution.