Как сумматор выполняет вычитание без знака? - PullRequest
3 голосов
/ 08 ноября 2011

Предположим, что A и B являются положительными целыми числами со знаком, тогда для A-B он рассчитывается с использованием дополнения A+2 к B.

Например, в 4-битной двоичной системе для целых чисел со знаком мы имеем 7-3=0111-0011=0111+1101=(1)0100, 1 в скобке - это бит для переноса. В соответствии с правилом переполнения для целого числа со знаком, мы знаем, что переполнения нет, и поэтому результат правильный.

Однако, для целых чисел без знака, что произойдет, если мы вычислим 7-3? Если мы используем то же самое, что мы упоминали выше:

7-3=0111-0011=0111+1101=(1)0100

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

Если мой анализ правилен, то не неправильно ли использовать сумматор для целочисленного вычитания без знака?

Ответы [ 4 ]

5 голосов
/ 08 ноября 2011

Ваш анализ неверен.На самом деле это зависит от модуля CPU ALU.:)

В первом случае вы используете 4-битное целое число, но вы забыли, что старший бит 4-битного целого числа равен знак !Таким образом, вы проверяете только статус Carry и Overflow, а не отрицательный бит состояния.

Обычно в двоичных арифметических операциях add и sub являютсято же самое для целых чисел со знаком и целых чисел без знака.Только затронутые флаги отличаются.

На самом деле вы должны учитывать:

  • при целочисленной арифметике со знаком Перенос , Переполнение и Отрицательные флаги.
  • только для целочисленной арифметики без знака Carry flags.

Подробное объяснение:

Изучение функции дополнения является отрицанием, чтобы получить противоположное отрицательное число от положительного и положительное от отрицательного.Мы можем сделать двоичное дополнение двумя способами.Рассмотрим оба случая для числа 3.

  1. При беззнаковой арифметике compl (3) = b'0011 'xor b'1111' + b'0001 '= b'1101' + Carry (Carry is set только при compl (0))
  2. При знаковых арифметических числах соблюдайте (3) = b'10000 '- b'0011' = b'1101 'что равно b'0000 '- b'0011' = b'1101 '+ Carry (Carry clear только при compl (0))

В первом случае функция дополнения также дополняет бит переноса, и у нас также есть вторая интерпретация флага переноса с именем займ .

Во втором случае все ясно.Если у нас есть перенос (переполнение) при дополнении, это означает, что нам нужен еще один переполнение для нормализации результата вычитания.

1 голос
/ 09 ноября 2011

В этом ответе на связанный вопрос есть пример кода на C, который показывает, как вычитать с помощью сложения. Код также устанавливает флаги переноса и переполнения и содержит простой «тест», который добавляет и вычитает несколько чисел и печатает результаты. Числа 8-битные.

РЕДАКТИРОВАТЬ: Формальное доказательство того, что можно использовать ADD вместо SUB для целых чисел без знака AND определить переполнение / недополнение без знака, как будто из SUB.

Допустим, мы хотим вычислить a - b, где a и b являются 4-битными целыми числами без знака, и мы хотим выполнить вычитание с помощью сложения и получить 4-битную разность и индикацию переполнения / переполнения, когда a .

a - b = a + (-b)
Поскольку мы работаем по арифметике по модулю 16, -b = 16-b. Таким образом,
a - b = a + (-b) = a + (16 - b)

Если мы выполняем обычное добавление без знака a и 16-b, условие переполнения для этого добавления, которое часто указывается процессором в его флаге carry, будет таким (напомним, что мы имеем дело с 4 -битные целые числа):

a + (16 - b)> 15
Давайте упростим это условие переполнения:
а + 16 - б> 15
+ 16> 15 + B
а + 1> б
а> б - 1

Давайте теперь вспомним, что мы имеем дело с целыми числами. Поэтому вышесказанное можно переписать так:
a> = b .
Это условие для получения флага переноса = 1 после добавления a и (16)-b. Если неравенство не выполняется, мы получаем carry = 0.

Давайте теперь вспомним, что нас интересовало переполнение / понижение из вычитания (a - b). Это условие a .

Ну, a> = b является полной противоположностью a .

Из этого следует, что флаг carry, полученный при добавлении a и (16)-b, является обратной величиной переполнения вычитания, или, другими словами, обратной borrow флаг, который вы получите, вычитая b непосредственно из a, используя соответствующую инструкцию вычитания (например, SUB).

Просто переверните носитель или обращайтесь с ним наоборот.

0 голосов
/ 16 июля 2019

Ваш анализ верен.

Используйте

OVERFLOW = EXOR (CARRY OUT, ADD '/ SUB)

, чтобы определить переполнение для обоихсложение без знака и вычитание без знака (с использованием сложения дополнения 2) для отдельной интерпретации.

При переполнении без знака указывается

CARRY OUT = 1

Правильный результат обозначается

CARRY OUT = 0

Но

ADD '/ SUB = 0

- для сложения

Так что в любом случае переполнение обозначается как 1.

Аналогично

При беззнаковом вычитании переполнение указывается как

CARRY OUT= 0

Правильный результат обозначен

CARRY OUT = 1

Но

ADD '/ SUB = 1

для вычитания

Так что в любом случае переполнение обозначается как 1.

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

0 голосов
/ 08 ноября 2011

Это немного сложно понять, но ... У меня был какой-то VHDL, где я это делал.У меня был ЦП с областью памяти, которая была неподписана и значение смещения было подписано.

architecture Behavioral of adder16 is
signal temp: std_logic_vector (16 downto 0);
begin
eval: process(vectA,vectB,temp)
begin
temp <=(('0'& vectB)  + (vectA(15) & vectA));
output <= temp( 15 downto 0);
end process;
end Behavioral;
...