Как обнаруживается переполнение на двоичном уровне?

Я читаю учебник "компьютерная организация и дизайн" Хеннесси и Паттерсона (4-е издание). На странице 225 они описывают, как обнаруживается переполнение в арифметике дополнения signed, 2. Я просто не могу понять, о чем они говорят.

" Как мы обнаруживаем [переполнение] , когда оно тут произойти? Ясно, добавление или вычитание двух 32-разрядных чисел может дать результат, требующий 33 бит полностью выраженный."

конечно. И ему не понадобится 34 бита, потому что даже самое маленькое 34-битное число вдвое меньше самого маленького 33-битного числа, и мы добавляем 32-битные числа.

" отсутствие 33-го бита означает, что при переполнении бит знака устанавливается с помощью стоимостью результата вместо правильного знака результат."

Что это значит? Бит знака устанавливается с "значением" результата... смысл его установить как если результат был неподписан? И если да, то как это следует из отсутствия 33-го бита?

"поскольку нам нужен только один дополнительный бит, только бит знака может быть неверной."

и вот где они потеряли меня полностью.

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

кроме того, это относится только к беззнаковым числам, верно? Если вы добавляете подписанные числа, конечно, обнаружение переполнения намного проще. Если последний сумматор ALU устанавливает бит переноса, происходит переполнение.

примечание: Я действительно не знаю, какие теги здесь уместен, не стесняйтесь редактировать их.

3 ответов


в любое время, когда вы хотите иметь дело с такими элементами alu, будь то сложение, вычитание, умножение и т. д., Начните с 2 или 3-битных чисел, гораздо проще получить ручку, чем 32 или 64-битные числа. после 2 или 3 бит не имеет значения, если это 22 или 2200 бит, все это работает точно так же оттуда. В принципе, вы можете вручную, если хотите, сделать таблицу всех 3-битных операндов и их результаты такими, чтобы вы могли визуально изучить всю таблицу, но таблицу всех 32-битных операндов против всех 32 бит операнды и их результаты не могут сделать это вручную в разумное время и не могут визуально изучить всю таблицу.

теперь двойки дополняют, это просто схема для представления положительных и отрицательных чисел, и это не какая-то произвольная вещь, у нее есть причина, причина безумия в том, что ваша логика сумматора (которая также использует вычитатель, который является той же самой вещью, которую использует множитель) не заботится о неподписанных или подписанных. Он не знает разницы. Вы, программист, заботитесь о моем трехбитовом мире, бит-Паттер 0b111 может быть положительной семеркой (+7) или отрицательной. Тот же битовый шаблон, подайте его в логику добавления, и то же самое выйдет, и ответ, который выйдет, я могу интерпретировать как дополнение без знака или двоек (если я интерпретирую операнды и результат все как без знака или все как дополнение двоек). Дополнение Twos также имеет функцию, что для отрицательных чисел наиболее значимым битом (msbit) является установлено, для положительных чисел это ноль. Так что это не знак "плюс" величины, но мы еще поговорим об msbit является битом знака, потому что за исключением двух специальных номеров, что то, что он говорит нам, знак числа, остальные биты самом деле говорит о масштабе их просто не беззнаковая величина, как вы могли бы в знак+, величина нотации.

Итак, ключ ко всему этому вопросу-понимание ваших пределов. Для 3-битного номера без знака наш диапазон от 0 до 7, 0b000 в 0b111. для интерпретации с 3-битной подписью (дополнение двоек) наш диапазон составляет от -4 до +3 (от 0b100 до 0b011). Если вы добавите 7+1, 0b111 + 0b001 = 0b1000, но у нас есть только 3-битная система, так что 0b000, 7+1 = 8, мы не можем представить 8 в нашей системе, так что это переполнение, потому что мы интерпретируем биты как неподписанные мы смотрим на "переполнение без знака", которое также известно как бит переноса или флаг. Теперь, если мы возьмем те же самые биты, но интерпретируем их как подписанные, затем 0b111 (-1) + 0b001 (+1) = 0b000 (0). Минус один плюс один-ноль. Нет переполнения, "подписанное переполнение" не установлено...Что такое подписанное переполнение?

во-первых, что такое "переполнение без знака".

причина, по которой "все работает одинаково", независимо от того, сколько бит у нас есть в наших регистрах, ничем не отличается от математики начальной школы с базовыми 10 (десятичными) числами. Если вы добавите 9 + 1, которые оба находятся в столбце ones, вы скажете, что 9 + 1 = ноль несут 1. вы носите один к столбцу tens тогда 1 плюс 0 плюс 0 (вы заполнили два нуля в столбце tens) равно 1 переносу нуля. у вас есть 1 в столбце tens и ноль в столбце ones

  1
  09
 +01
====
  10

что делать, если мы объявили, что мы ограничены только номерами в столбце ones, нет места для столбца tens. Ну, что нести бит ненулевой означает, что у нас есть переполнение, чтобы правильно вычислить результат, нам нужен другой столбец, то же самое с binary

  111 
   111
 + 001
=======
  1000

7 + 1 = 8, но мы не могу сделать 8, если мы объявим 3-битную систему, мы можем сделать 7 + 1 = 0 с набором битов переноса. Вот где красота дополнения twos приходит в:

  111 
   111
 + 001
=======
   000

если вы посмотрите на вышеуказанное добавление трех битов, вы не можете сказать, глядя, если это 7 + 1 = 0 с набором битов переноса или если это -1 + 1 = 0.

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

подписал переполнения. Вид академического ответа-если перенос столбца msbit не соответствует выполнению. давайте возьмем несколько примеров в нашем 3-битном мире. Таким образом, с дополнением двоек мы ограничены от -4 до +3. поэтому, если мы добавим -2 + -3 = -5, что не будет работать правильно? Чтобы выяснить, что такое минус два, мы делаем инверт и добавляем один 0b010, инвертированный 0b101, добавляем один 0b110. минус три-0b011 - > 0b100 -> 0b101

Итак, теперь мы можем сделать это:

  abc
  100 
   110
 + 100
======
   010

если вы посмотрите на число под b, которое является "переносом" в столбец msbit, число под a 1, является выполнением, эти два не совпадают, поэтому мы знаем, что есть "подписанное переполнение"

давайте попробуем 2 + 2 = 4

  abc
  010
   010
 + 010
======
   100

вы можете сказать, но это выглядит правильно, конечно, без знака, но мы делаем здесь подписанную математику, поэтому результат на самом деле -4 не положительный 4. 2 + 2 != -4. перенос, который находится под b, равен 1, перенос msbit равен нулю, перенос и перенос не совпадают. подписанное переполнение.

существует ярлык для выяснения подписанного переполнения без необходимости смотреть на перенос (или выполнять). если (msbit (opa) = = msbit(opb)) & & (msbit(res)!= msbit (opb) ) подписанное переполнение, иначе нет подписанного переполнения. opa - один операнд, opb-другой и res результат.

   010
 + 010
======
   100

возьмите это +2 + +2 = -4. msbit(opa) и msbit (opb) равны, и результат msbit не равен opb msbit, поэтому это подписанное переполнение. Вы можете подумать об этом, используя эту таблицу

x ab cr 
0 00 00
0 01 01
0 10 01
0 11 10 signed overflow
1 00 01 signed overflow
1 01 10
1 10 10
1 11 11

эта таблица - все возможные комбинации, если переносить бит, операнд a, операнд b, выполнять и бит результата для одного столбца поверните голову влево, чтобы увидеть, что этот x-это перенос, столбцы a и b-это два операнда. cr как пара является результатом xAB 011 означает 0+1+1 = 2 десятичных знака что 0b10 бинарных. Таким образом, принимая правило, которое было продиктовано нам, что если перенос и выполнение не совпадают, это подписанное переполнение. Ну, два случая, когда элемент в столбце x не соответствует элементу в столбце c, указаны те случаи, когда входы a и b совпадают друг с другом, но бит результата противоположен a и b. Поэтому, предполагая, что правило правильно, этот быстрый ярлык, который не требует знания того, что такое биты переноса, скажет вам, был ли подписанное переполнение.

теперь Вы читаете книгу H&P. Что, вероятно, означает mips или dlx, ни mips, ни dlx не имеют дело с флагами carry и signed, как это делает большинство других процессоров. mips-это не лучший первый набор инструкций IMO в первую очередь по этой причине, их подход никоим образом не ошибочен, но, будучи странным, вы всегда будете думать по-другому и переводить при переходе на большинство других процессоров. Где, если вы узнали типичные флаги znvc (нулевой флаг, отрицательный флаг, V=signed overflow, c=carry или unsigned overflow), тогда вам нужно только перевести при переходе на mips. Обычно они вычисляются на каждой операции alu (для процессоров типа non-mips), вы увидите, что подписанное и неподписанное переполнение вычисляется для add и subtract. (Я привык к более старым mips, возможно, этот ген книг и текущий набор инструкций имеет что-то другое). Вызывая его addu, добавьте unsigned прямо в начале mips после изучения всего вышеизложенного о том, как схема сумматора не заботится о signed vs unsigned, это огромная проблема с mips, она действительно ставит вас в неправильное мышление для понимания чего-то такого простого. Приводит к убеждению, что существует разница между подписанным добавлением и неподписанным добавлением, когда его нет. Только флаги переполнения вычисляются по-разному. Теперь умножьте и разделите, безусловно, есть дополнение двойки против беззнаковой разницы, и вам в идеале нужно знаковое умножение и беззнаковое умножение или вам нужно чтобы справиться с ограничением.

я рекомендую простое (в зависимости от того, насколько сильна ваша битовая манипуляция и дополнение двоек) упражнение, которое вы можете написать на каком-то языке высокого уровня. В основном возьмите все комбинации беззнаковых чисел от 0 до 7, добавленные к 0 до 7, и сохраните результат. Распечатайте как десятичный, так и двоичный (три бита для операндов, четыре бита для результата), а также если результат превышает 7 переполнений печати. Повторите это, используя подписанные переменные, используя числа от -4 до +3 добавлены к -4 до +3. выведите как десятичное число со знаком+/ -, так и двоичное. Если результат меньше -4 или больше, чем +3 переполнения печати. Из этих двух таблиц вы должны видеть, что приведенные выше правила верны. Глядя строго на операнд и результирующие битовые шаблоны для разрешенного размера (в этом случае три бита) , вы увидите, что операция сложения дает тот же результат, тот же битовый шаблон для данной пары входов независимо от того, являются ли эти битовые шаблоны считается неподписанным или дополнением двоек. Также вы можете проверить, что переполнение без знака-это когда результат должен использовать этот четвертый столбец, есть выполнение msbit. для подписанного, когда carry in не соответствует carry out, который вы видите, используя ярлык, глядя на msbits операндов и результата. Еще лучше, чтобы ваша программа делала эти сравнения и распечатывала что-то. Поэтому, если вы видите примечание в своей таблице, что результат больше 7 и примечание в вашей таблице, что бит 3 установлен в результате, тогда вы увидите для таблицы без знака, которая всегда имеет место (ограничена входами от 0 до 7). И более сложный, signed overflow, всегда, когда результат меньше -4 и больше 3 и когда верхние биты операнда совпадают, а верхний бит результата не соответствует операндам.

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

другая половина двойки дополняет магию. аппаратное обеспечение не имеет логики вычитания. один из способов "конвертировать" в дополнение к двойкам - "инвертировать и добавить один". если бы я хотел вычесть 3-2, используя двойки, дополняющие то, что на самом деле происходит, это то же самое, что и +3 + (-2), и чтобы получить от +2 до -2, мы инвертируем и добавляем один. Глядя на наше дополнение к начальной школе, вы заметили дыру в переносе на первой колонке?

  111H
   111
 + 001
=======
  1000

я поставил H выше где дыра. Хорошо, что carry in bit добавляется к операндам, верно? наша логика сложения не является двухвходовым сумматором, это трехвходовой сумматор да? большинство столбцов должны добавить три однобитовых числа, чтобы вычислить два операнда. Если мы используем три входных сумматора на первом столбце, теперь у нас есть место ... добавить его. Если бы я хотел, чтобы вычесть 3 - 2 = 3 + (-2) = 3 + (~2) + 1 что это:

    1
  011
+ 101
=====

прежде чем мы начнем, и заполнил это:

 1111
  011
+ 101
=====
  001

3 - 2 = 1.

что логика-это:

если add, то carry in = 0; операнд b не инвертирован, carry out не инвертирован. если вычесть, то carry in = 1; операнд b инвертирован, carry out может быть инвертирован.

добавление выше показывает выполнение, я не упоминал, что это была неподписанная операция 3 - 2 = 1. Я использовал некоторые трюки дополнения двоек для выполнения операции без знака, потому что здесь снова независимо от того, интерпретирую ли я операнды как подписанные или неподписанные правила применяются к if add или if subtract. Почему я сказал, что выполнение может быть инвертировано, так это то, что некоторые процессоры инвертируют выполнение, а некоторые нет. это связано с каскадными операциями, например, с 32-битной логикой сложения и использованием флага переноса и добавления с переносом или вычитанием с помощью инструкции заимствования, создающей 64-битное добавление или вычитание или любое кратное размеру Базового регистра. скажем, у вас есть два 64-битных номера в 32-битной системе a: b + c: d, где a:b - 64-бит число, но оно хранится в двух регистрах a и b, где a-верхняя половина, А b-нижняя половина. Итак, a:b + c:d = e: f на 32-битной системе без знака, которая имеет бит переноса и добавляет с carry:

add f,b,d
addc e,a,c

add оставляет свой бит выполнения от верхней самой битовой полосы в флаге переноса в регистре состояния, инструкция addc add with carry принимает операнды a+c, и если бит переноса установлен, то добавляет еще один. a+c+1 положить результат в e и выполнить в переноске флаг, так

add f,b,d
addc e,a,c
addc x,y,z

является 96-битным дополнением и так далее. Здесь снова что-то очень чуждое mips, так как он не использует флаги, как другие процессоры. Где инвертировать или не инвертировать для подписанного выполнения-это вычитание с заимствованием для конкретного процессора. для вычитания:

если вычесть, то carry in = 1; операнд b инвертирован, carry out может быть инвертирован.

для вычитания с заимствованием вы должны сказать, если флаг переноса из регистр состояния указывает на заимствование, тогда перенос-0, иначе перенос-1, и вы должны получить выполнение в регистр состояния, чтобы указать заимствование.

в основном для нормального вычитания некоторые процессоры инвертируют операнд b и продолжают в пути и выполняют на выходе, некоторые процессоры инвертируют операнд b и выполняют в пути, но не инвертируют выполнение на выходе. Затем, когда вы хотите сделать условную ветвь, вам нужно знать, если перенос флаг означает больше или меньше (часто синтаксис будет иметь ветвь, если больше или ветвь, если меньше, а иногда говорит вам, какая из них является упрощенной ветвью, если carry set или ветвь, если carry clear). (если вы не" получите " то, что я только что сказал, это еще один столь же длинный ответ, который ничего не будет означать, пока вы изучаете mips).


поскольку 32-разрядные целые числа со знаком представлены 1 знаком-битом и 31 битом для фактического числа, мы эффективно добавляем два 31 бит-числа. Следовательно, 32-й бит (бит знака) будет там, где будет видно переполнение.

" отсутствие 33-го бита означает, что при переполнении бит знака устанавливается со значением результата вместо правильного знака результата."

представьте себе следующее добавление двух положительных чисел (16 бит к simpify):

  0100 1100 0011 1010  (19514)
+ 0110 0010 0001 0010  (25106)
= 1010 1110 0110 1100  (-20884 [or 44652]) 

для суммирования двух больших отрицательных чисел, однако, потребуется дополнительный бит

  1100 1100 0011 1010  
+ 1110 0010 0001 0010  
=11010 1110 0110 1100  

обычно процессор имеет этот 33-й бит (или любой бит, который он работает на +1), представленный как бит переполнения в микроархитектуре.


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

Что это значит? Бит знака устанавливается с "значением" результата...

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

"поскольку нам нужен только один дополнительный бит, только бит знака может быть неверной."

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

Это следствие того, что было описано выше: путаница между значением бита знака из-за переполнения.