2011-01-10 3 views
4

Я более чем наполовину участвую в обучении, и я знаком с концепцией того, как целые числа с подписью и без знака представлены в битах, я знаю, что может показаться странным вопрос, ответ на который будет довольно очевидным, но Мне интересно, если использование арифметической операции, такой как сложение, имеет смысл для пары чисел, одна из которых считается подписанной, а другая без знака, я думал о нескольких примерах, подобных приведенным ниже, что даст правильный результат:будет делать арифметическую операцию над парой подписанных и неподписанных чисел?

10000001 (1-байтовое целое число без знака, и считать, что эквивалентно 129)
+
11111111 (1-байтовое целое число, и считается подписанным (в дополнительном коде системы), что эквивалентно -1)


10000000 (1-байтовое целое число, а в беззнаковой логике, эквивалентные 128)

Теперь, если верхнее значение было в AL регистр, и мы имели следующий код инструкции (в формате GAS):

addb -1, %al 

, тогда флаг переноса (CF) регистра EFLAGS будет установлен после выполнения операции и будет информировать о переполнении, которое на самом деле не произошло, и, возможно, потому, что есть одно беззнаковое число в терминах переполнения флага переполнения (OF) Регистр EFLAGS следует указать. Поэтому я смущен, если делать такую ​​вещь всегда разумно.

ответ

1

Я нашел это очень хороший article по этому вопросу, которая была моей главной заботой и ответ ясен после прочтения статьи.

3

Независимо от того, подписан ли номер или операция или нет, это просто вопрос интерпретации. Что произойдет, когда вы сделаете добавление, так это то, что два числа добавляются вместе, чтобы сделать 10000000 с 1 в флагом переноса (потому что он «ушел с фронта»). Затем ваши последующие операции интерпретируют то, что это значит (если вы используете бит в другом месте, это похоже на то, что вы рассматриваете операцию как беззнаковое добавление без обертывания; если вы отбросите бит, это похоже на то, что вы подписали Добавить).

+0

Это верно только в том случае, если результат такого же размера, как и все операнды. Обычно процессоры имеют многократные инструкции, размер результата которых в два раза превышает размер операнда; некоторые из них также имеют инструкции добавления, в которых операнды имеют разные размеры (например, как «ADD.W D3, A5» на 68000, так и 'ADD * +' на TMS32050 будут подписывать-расширять 16-битное значение и добавлять его к 32 В TMS также есть «ADDU * +», чтобы добавить 16-разрядное значение без знака в 32-разрядный регистр. – supercat

3

На двоичном уровне, есть только одна операция сложения:

0101 + (5) 
1010 = (unsigned 10 or signed -6) 
-------- 
1111 (unsigned 15 or signed -1) 

Что о перенесенных и переливных флагах, они оба установлены в соответствии с простыми правилами. CF можно использовать для обнаружения oveflow iff, мы считаем, что операнды были без знака, а OF для обнаружения oveflow iff мы рассматриваем обе подписанные. Оба эти флажка устанавливаются в соответствии с результатом, и вам решать, какие из них использовать.

Фактическая формула для флага является

OF = CF xor MSB_of_result. 

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

1

Подписанные и неподписанные интерпретации. Как правило, инструкция по сборке имеет документированную интерпретацию. Я не знаю ни одной архитектуры, где есть инструкция ADD-SIGNED-UNSIGNED, которая интерпретирует один из своих аргументов как знаковое значение, а одно - как unsigned. В этом тоже мало смысла. С 2s дополнением целочисленной арифметикой, в любом случае будет только разница в некоторых регистрах флага.

+0

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

6

Математически вы не добавляете подписанное или неподписанное число. Имеются только значения modulo 2 (при условии, что у вас есть 32-разрядные регистры).Такие значения охватывают диапазон 2 последовательных целых чисел, но вы можете интерпретировать этот диапазон как начало практически в любом месте. «Подписанные» и «беззнаковые» - это всего лишь две такие интерпретации.

Другими словами, с 4-битными регистрами неподписанная интерпретация «1011» составляет одиннадцать, а подписанная интерпретация - минус пять. Но есть только одно значение (которое математики обычно называют «одиннадцатью по модулю 2 », потому что математики традиционно любят неподписанную интерпретацию). Например, если вы добавите «0110» к этому значению (которое равно «шестерке» как в подписанных, так и неподписанных интерпретациях), тогда вы получите «0001», что является правильным значением: минус пять плюс шесть уроков один, а одиннадцать плюс шесть семнадцать, которая также равна единице, когда уменьшается по модулю 2 (семнадцать один плюс шестнадцать; «сокращение по модулю 2 » о делении на шестнадцать [это 2 ] и сохраняя остаток только).

Другой способ сказать следующее: число (двоичных) цифр для численного значения концептуально бесконечно слева. Регистр CPU сохраняет только 32 самых правых бита. Беззнаковая интерпретация предполагает, что условно все левые биты равны нулю. Подписанная интерпретация заключается в предположении, что условно, что все левые биты имеют то же значение, что бит 31 (т. Е. Все равны нулю или все они равны единице). В любом случае, когда вы выполняете сложение (или вычитание или умножение), перенос распространяется справа налево, а не наоборот, поэтому значения тех игнорируемых битов не имеют никакого отношения к 32-битовому результату. Таким образом, существует только один «дополнительный» код операции, который нисколько не интересует, являются ли его операнды в мозгу программиста «подписанными» или «беззнаковыми».

Подпись должна быть принята во внимание при выполнении операции не, совместимой с модульной арифметикой. Преобразование в последовательность десятичных цифр для отображения - такая операция. Однако более частым случаем является сравнение. Значения по модулю 2 не заказываются; они находятся в виде циклической петли (когда вы добавляете 1 к 2 -1, и уменьшаете по модулю 2 , вы возвращаетесь к 0). Сравнение имеет смысл только тогда, когда вы считаете целыми числами во всем диапазоне целых чисел. В этот момент вы должны решить, используете ли вы подписанную или неподписанную интерпретацию. Именно поэтому процессоры x86 предлагают как jg (скачок, если больше, подписанная интерпретация) и ja (скачок, если выше, неподписанная интерпретация).

+0

+1 для получения наиболее полного и общего ответа. – ruslik

Смежные вопросы