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

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

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

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

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

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

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

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

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

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

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

Ответ 1

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

Теперь twos дополняет, это всего лишь схема для представления положительных и отрицательных чисел, и это не какая-то произвольная вещь, в которой есть причина, причина безумия заключается в том, что ваша логика суммирования (которая также является тем, что использует вычитатель, является тем же самым типом, который использует множитель) НЕ УХОДИТ НЕ ПОДПИСАНО ИЛИ ПОДПИСАНО. Он не знает разницы. ВАМ программист заботится о моем трехбитом мире, бит patter 0b111 может быть постинсульманским семи (+7), или он может быть отрицательным. Один и тот же шаблон бита, передайте его логике добавления и выйдет одно и то же, и ответ, который появляется, я могу выбрать для интерпретации как беззнаковый или двухкомпонентный (пока я интерпретирую операнды и результат все как без знака или все как двойной набор). Компонент Twos также имеет функцию, которая для отрицательных чисел устанавливается старший бит (msbit), для положительных чисел - нуль. Таким образом, это не знак плюс величина, но мы по-прежнему говорим о том, что msbit является знаковым битом, потому что, за исключением двух специальных чисел, которые это говорит нам, знак числа, другие биты фактически говорят нам о величине, которую они представляют просто не значение без знака, как у вас может быть в знаке + величина.

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

Во-первых, что такое "неподписанное переполнение".

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

  1
  09
 +01
====
  10

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

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

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

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

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

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

Поднятое переполнение. Тип академического ответа заключается в том, что перенос столбца msbit не соответствует выполнению. давайте возьмем некоторые примеры в нашем мире с 3 битами. Таким образом, с дополнением twos мы ограничены -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 равно нулю, перенос и выполнение не совпадают. подписанное переполнение.

есть ярлык для определения подписанного переполнения без необходимости смотреть на перенос (или выполнение). if (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 не имеют дело с несущими и подписанными флагами так, как это делают большинство других процессоров. mips - это не лучший первый набор команд ИМО, в первую очередь по этой причине, их подход ни в коем случае не является неправильным, но, будучи странным, вы будете тратить навсегда мышление по-разному и переводить при переходе на большинство других процессоров. Если вы узнали типичные флаги znvc (флаг нуля, отрицательный флаг, v = подписанный переполнение, c = перенос или неподписанное переполнение), тогда вам нужно перевести только при переходе к mips. Обычно они вычисляются на каждой операции alu (для процессоров типа non-mips) вы увидите, что при добавлении и вычитании вычитается переполнение переполнения и без знака. (Я привык к старшим мадам, может быть, этот ген книг, а текущий набор команд имеет что-то другое). Называя это addu, добавьте unsigned прямо в начале mips, узнав все вышеперечисленное о том, как схема сумматора не заботится о подписанных vs unsigned, представляет собой огромную проблему с mips, которая действительно помещает вас в неправильный образ мышления для понимания чего-то такого простого. Приводит к убеждению, что существует разница между подписанным дополнением и беззнаковым добавлением, когда нет. Вычисляются только флаги переполнения. Теперь умножьте и разделите, что определенно есть двухкомпонентное дополнение к беззнаковой разнице, и вам в идеале требуется подписанное умножение и беззнаковое умножить или вам нужно иметь дело с ограничением.

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

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

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

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

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

    1
  011
+ 101
=====

прежде чем мы начнем и запустим его:

 1111
  011
+ 101
=====
  001

3 - 2 = 1.

Что делает логика:

если добавить, то нести в = 0; операнд b не инвертирован, выполнение не инвертируется. если вычесть, то нести в = 1; операнд b инвертирован, выполнение MIGHT BE инвертируется.

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

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

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

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

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

если вычесть, тогда нести в = 1; операнд b инвертирован, выполнение MIGHT BE инвертируется.

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

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

Ответ 2

Поскольку 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  

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

Ответ 3

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

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

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

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

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

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