Однако ясно, что это крайне неэкономично — байтов требуется в два раза больше, а старший полубайт при этом все равно всегда ноль. Потому BCD-числа при хранении в регистрах всегда упаковывают, занимая и старший разряд второй десятичной цифрой: скажем, число 59 при этом и запишется, как просто 59. Однако это не 59h! 59 в шестнадцатеричной форме есть 3Bh, как мы установили ранее, а наше 59 процессор прочтет, как 5∙16 + 9 = 89, что вообще ни в какие ворота не лезет! Поэтому перед проведением операций с упакованными BCD-числами их распаковывают, перемещая старший разряд в отдельный байт и заменяя в обоих байтах старшие полубайты нулями. Иногда для проведения операций с BCD в микропроцессоре или микроконтроллере предусмотрены специальные команды, так что самостоятельно заниматься упаковкой-распаковкой не требуется (такие инструкции есть, например, в системе команд знаменитого 8086, на котором был построен IBM PC). В качестве примера хранения чисел в BCD-формате можно привести значения часов, минут и секунд в энергонезависимых часах компьютера.
Правила двоичной арифметики значительно проще, чем десятичной, и включают две таблицы — сложения и умножения — несколько похожие на те же таблицы для логических переменных:
0 + 0 = 0 0∙0 = 0
0 + 1 = 1 0∙1 = 0
1 + 0 = 1 1∙0 = 0
1 + 1 = 10 1∙1 = 1
Как мы видим, правила обычного умножения одноразрядных двоичных величин совпадают с таковыми для логического умножения. Однако правила сложения отличаются, т. к. при сложении двух единиц результат равен 2 и у нас появляется перенос в следующий разряд. Так как умножение многоразрядных чисел сводится к сложению отдельных произведений, то там придется этот перенос учитывать (как это делается на практике, мы увидим при рассмотрении микроконтроллеров).
Возможно, вы удивитесь, но любая электронная схема (и микропроцессор не исключение) умеет только складывать. Свести умножение к сложению легко. А как свести к сложению вычитание и деление? Для этого придется познакомиться с тем, как в электронике представляют отрицательные числа.
Отрицательные числа
Самый простой метод представления отрицательных чисел — отвести один бит (логичнее всего старший) для хранения знака. По причинам, которые вы поймете далее, значение «1» в этом бите означает знак «минус», а «0» — знак «плюс». Как будут выглядеть двоичные числа в таком представлении?
В области положительных чисел ничего не изменится, кроме того, что их диапазон сократится вдвое: например, для числа в байтовом представлении вместо диапазона 0—255 мы получим всего лишь 0—127 (0000 0000–0111 1111). А отрицательные числа будут иметь тот же диапазон, только старший бит у них будет равен единице. Все просто, не правда ли?
Нет, неправда. Такое представление отрицательных чисел совершенно не соответствует обычной числовой оси, на которой влево от нуля идет минус единица, а затем числа по абсолютной величине увеличиваются. Здесь же мы получаем, во-первых, два разных нуля («обычный» 0000 0000, и «отрицательный» 1000 0000), во-вторых, оси отрицательных и положительных чисел никак не стыкуются, и выполнение арифметических операций превратится в головоломку. Поэтому поступим так: договоримся, что -1 соответствует число 255 (1111 1111), — 2 — число 254 (1111 1110) и т. д., вниз до 128 (1000 0000), которое будет соответствовать -128 (и общий диапазон всех чисел получится от -128 до 127). Очевидно, что если вы в таком представлении хотите получить отрицательное число в обычном виде, то надо из значения числа (например, 240) вычесть максимальное значение диапазона (255) плюс 1 (256). Если отбросить знак, то результат такого вычитания (16 в данном случае) называется еще
Вычитание
Что произойдет в такой системе, если вычесть, например 2 из 1? Запишем это действие в двоичной системе обычным столбиком:
00000001
— 00000010
В первом разряде результата мы без проблем получаем 1, а уже для второго нам придется занимать 1 из старших, которые сплошь нули, поэтому представим себе, что у нас будто бы есть девятый разряд, равный 1, из которого заем в конечном итоге и происходит:
(1) 00000001
— 00000010
-
11111111
На самом деле девятиразрядное число 1 0000 0000 есть не что иное, как 256, т. е. то же самое максимальное значение +1, и мы здесь выполнили две операции: прибавили к вычитаемому эти самые 256, а затем выполнили вычитание, но уже в положительной области для всех участвующих чисел. А что результат? Он будет равен 255, т. е. тому самому числу, которое, как мы договорились, представляет собой -1. Таким образом, вычитание в такой системе происходит автоматически правильно, независимо от знака участвующих чисел.