Главная /
Ассемблер /
Для чайников /
Введение /
Представление данных /
Что такое переполнение
Выше
мы уже говорили о переполнении. Пришло время разобраться с этим более подробно.
Допустим, мы складываем два целых числа при работе с числами со знаком:
01101110
+
01101110
=
11011100
Или в десятичной системе 110 + 110 = 220. Но мы то работаем с числами со знаком.
В этом случае максимальное значение для байта равно 127. А полученное нами двоичное
число будет на самом деле отрицательным числом –36 (см. раздел
Отрицательные числа).
В случае переполнения устанавливается флаг OF в регистре флагов (см. раздел
Регистр флагов).
Вернёмся к примеру сложения двух чисел:
01101110
+
10010010
=
100000000
Мы складывали отрицательное число 110 с таким же положительным и в итоге получили ноль,
что вполне справедливо. А вот если бы мы работали с числами без знака, то это были бы уже
другие числа и другой результат (точнее, по сути тот же самый, но формально другой)
01101110b = 110
10010010b = 146
110 + 146 = 256
Если мы запишем в программе такой код (прибавим к числу в регистре AL число,
указанное в команде ADD – сложение):
MOV AL, 110
ADD AL, 146
то в результате в регистре AL у нас будет не 256, а 0, потому что регистр AL может
работать только с одним байтом информации, а максимальное беззнаковое число,
которое можно «запихнуть» в байт – это число 255. Число 256 это
100000000
то есть число, которое для записи в двоичной форме требует 9 разрядов.
То есть единица находится в старшем 8-м разряде, а все младшие 8 разрядов (с 0 по 7)
заполнены нулями. Именно поэтому в 8-разрядном регистре AL после выполнения операции
сложения чисел 110 и 146 будет 0. В таком случае будет установлен флаг CF в регистре флагов,
так как результат не поместился в регистре-приёмнике и произошёл перенос единицы из старшего бита.
Ситуации, подобные описанным выше, называются переполнением. То есть
переполнение – это когда результат какой-либо операции не помещается
в предназначенный для этого результата регистр. Разумеется, при переполнении результатом
может быть и не ноль, а другое число. Например, при сложении чисел 110 и 147 в регистре
AL будет число 1 (а не 257, как нам хотелось бы).
Как вы понимаете, переполнение – это один из подводных камней на пути программиста.
Ведь совершенно неожиданно при увеличении зарплаты с 200 до 256 вы можете получить ноль.
И это будет справедливо, потому что неожиданно это будет только для плохого программиста.
Хороший программист при работе с числами всегда помнит о вероятности переполнения/переноса
и принимает соответствующие меры. Например, для описанного выше случая избежать переполнения
можно так:
MOV AX, 110
ADD AX, 146
В результате в регистре AX у нас будет число 256, потому что регистр AX – это 16-разрядный
регистр, в который при работе с беззнаковыми числами можно «впихнуть» число вплоть до
значения 65 535. См. также раздел
Регистры процессора.
Однако всегда найдутся ситуации, когда переполнение или перенос всё-таки произойдёт.
Как в этом случае определить, правильный ли результат вы получили? Для этого существует
регистр флагов, который мы рассмотрим в следующем разделе.