Ответ 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, если перенос очищен). (если вы не "получите" то, что я только что сказал там, это еще один одинаково длинный ответ, который не будет означать ничего, пока вы изучаете мип).