Двоичная арифметика В этой главе рассмотрим выполнение микропроцессором (МП) арифметических операций с двоичными числами. Двоичное сложение Сложение двоичных чисел подобно сложению десятичных. В обоих случаях операции начинаются с обработки наименьших значений цифр в крайней справа позиции. Если результат сложения наименьших значащих цифр двух слагаемых не помещается в соответствующем разряде результата, то происходит перенос. Цифра, переносимая в соседний слева разряд, добавляется к содержимому последнего. Перенос возникает, если результат сложения цифр одноименных разрядов больше 9 при использовании десятичной арифметики, и только 1 в случае двоичной. Рассмотрим пример: десятичная двоичная перенос 11 1111 1110 слагаемое 099 0110 0011 слагаемое 095 0101 1111 сумма 194 1100 0010 Двоичная арифметика намного проще десятичной, т.к. перенос возникает в единственном случае - при двух единицах в одноименных разрядах. Двоичное вычитание Как и в случае сложения, различия выполнения в двоичной и десятичной форме состоят лишь в особенностях поразрядных операций. Если содержимое разряда уменьшаемого меньше содержимого одноименного разряда вычитаемого, то имеет место заем. В двоичной системе это происходит в том случае, когда из нуля вычитается единица. Рассмотрим пример: десятичная двоичная заем 1 110 0000 уменьшаемое 109 0110 1101 вычитаемое 049 0011 0001 разность 060 0011 1100 1 Двоичные числа в дополнительном коде Существует несколько способов представления отрицательных двоичных чисел. Большинство из них не соответствует возможностям аппаратной основы арифметико-логических устройств (АЛУ). Представление числа посредством величины и знака, причем бит знака занимает самый старший разряд двоичного числа. Если число положительное - бит знака равен 0, если оно отрицательное, то этот бит равен 1. Аналогично и в обратном коде, который формируется заменой всех нулей числа на единицы, а всех единиц - на нули. Поскольку знаковый разряд положительного числа равен 0, то в обратном коде отрицательного числа 1. Несмотря на простоту правила формирования обратного кода работа с ними вызывает ряд трудностей. Так нулевой результат может быть представлен комбинацией или двоичных нулей, или двоичных единиц. В микроЭВМ широко используется представление отрицательных чисел в дополнительном коде (код дополнения до 2). При таком представлении исчезает двусмысленность представления нулевого результата, присущая способу в обратном коде. Формирование дополнительного кода или сокращенно дополнения состоит из двух операций получения обратного кода и дополнения единицы. Пример: число 410 в двоичной форме 0000 0100 обратный код числа 1111 1011 добавляемая 12 1 число 410 в дополнительно коде 1111 1100 Для представления двоичного числа в дополнительном коде можно пользоваться другим способом. В поисках первого бита равного единице просматривают справа налево разряды числа, начиная с наименьшего по значимости. До тех пор, пока встречаются нули, их копируют в одноименные разряды результата. Первая встретившаяся единица также копируется в соответствующий разряд, но каждый последующий бит исходного числа заменяется на обратный. Рассмотрим небольшую таблицу: Десятичный эквивалент 8 - разрядное двоичное число двоичного числа без знака 0000 0000 0000 0001 0000 0010 ---…--0111 1101 0111 1110 0 1 2 ---…--125 126 2 двоичного числа со знаком (отрицательные в дополнительном коде) +0 +1 +2 ---…--+125 +126 0111 1111 ---…--1000 0000 1000 0001 1000 0010 ---…--1111 1101 1111 1110 1111 1111 127 ---…--128 129 130 ---…--253 254 255 +127 ---…---128 -127 -126 ---…---3 -2 -1 Согласно этой таблице арифметические операции над двоичными числами без знака ничем не отличаются от операций над числами со знаком. Это существенно упрощает аппаратную реализацию операций в МП. В общем случае при сложении или вычитании чисел со знаком результат есть число со знаком, если при этом старший бит равен единице, то результат - отрицательное число в дополнительном коде. Если требуется определить абсолютное значение результата последний необходимо представить в обратном коде, а затем прибавить единицу. Пример 1: Вычислим разность (58 – 23) число 2310 дополнительный код 2310 0001 0111 1110 1001 вычисление разности 58 0011 1010 число 5810 – – 23 1110 1001 дополнительный код 2310 15 1 0010 0011 результат 1510 единица переноса отбрасываемая в случае положительного результата Пример 2: Вычисление разности (26 – 34) число 3410 дополнительный код 3410 0010 0010 1101 1110 вычисление разности 0001 1010 число 2610 34 1101 1110 -8 1111 1000 дополнительный код 3410 результат в дополнительном коде, значит число отрицательное 26 – – определим абсолютное значение: 1111 1000 0000 0111 1 0000 1000 дополнительный код разности обратный код единица к обратному коду абсолютное значение 810 3 Двоичное умножение Умножение – это быстрый способ сложения нескольких одинаковых чисел. При умножении одного числа на другое одно число называется множимым, другое - множителем. Умножение выполняется поразрядно. Часто возникает необходимость переноса в следующий по старшинству разряд. По завершению умножения множимого на значение младшего разряда множителя получается первое частичное произведение. В результате умножения множимого на значение следующего по старшинству разряда множителя формируется второе частичное произведение. Подобная процедура повторяется необходимое число раз. Для получения результирующего произведения, смещенные относительно друг друга частичные произведения складываются с учетом переноса. Рассмотрим пример: 17 множитель * 12 34 17 100 204 множимое первое частичное произведение второе частичное произведение перенос результирующее произведение Поскольку множитель состоит из двух разрядов, получаются два частичных произведения, сложение которых вызывает перенос в разряд сотен. В двоичной форме: 0001 0001 множимое 1710 * 0000 1100 0000 0000 0000 0000 0001 0001 0001 0001 0000 0000 0000 0000 0000 0000 0000 0000 000 0000 0000 0000 0000 0000 1100 1100 множитель 1210 первое частичное произведение второе восьмое частичное произведение перенос результат 20410 Перенос всегда будет равен 0, т.к. при умножении двоичных цифр его не возникает. Итак, получено восемь частичных произведений, поскольку множитель состоит из 8 разрядов. Третье частичное произведение - копия множимого, только оно сдвинуто относительно множимого на два двоичных разряда, поскольку для получения этого частичного произведения в качестве множителя используется значение третьего разряда, равного 1. Аналогично четвертое частичное произведение. Остальные равны нулям, как и соответствующие им разряды множителя. Сложение всех частичных произведений и дает конечный результат. 4 Создан способ выполнения двоичного умножения, получивший название умножения путем сдвига и сложения. Перечислим основные правила этого способа: 1. Формирование первого частичного произведения. Если значение младшего разряда множителя равно 0, то и результат равен 0, если значение этого разряда равно 1, то результат является копией множимого. 2. Правило сдвига. При использовании очередного разряда множителя для формирования частичного произведения производится сдвиг множимого на один разряд влево. 3. Правило сложения. Каждый раз, когда значение разряда множителя равно 1, к результату необходимо прибавить множимое, расположенное в позиции, определенной правилом сдвига. 4. Определение результирующего произведения. Искомое произведение есть результат выполнения всех операций сдвига и сложения. Попробуем применить правило к нашему примеру: 00010001 * 00001100 00010001 + 00010001 000110011 Подобный метод возможен лишь благодаря тому, что при умножении двоичного числа на 0 получается 0, а результат умножения двоичного числа на 1 есть само это число. Двоичное деление Деление - это операция, обратная умножению. Иначе говоря, при делении операцию вычитания повторяют до тех пор, пока уменьшаемое не станет меньше вычитаемого. Число этих повторений показывает, сколько раз вычитаемое укладывается в уменьшаемом. Рассмотрим процедуру деления на примере: Десятичное деление 204 12 12 17 84 84 0 Двоичное деление 1100 1100 1100 1100 0 1100 10001 1100 0 Процедура деления нам знакома и начинается с анализа старших разрядов делимого 20410 и делителя 1210. Мы обнаруживаем, что число 12 укладывается в число 20 только один раз, поскольку остаток (8) меньше делителя (12). Объединяя остаток со следующей цифрой делимого, получаем число 84 и снова определяем, сколько раз делитель (12) укладывается в 84. Результатом деления является частное, равное 17. Аналогично происходит и при делении в двоичной системе. Все, казалось бы, просто, но организовать такую процедуру в машине не столь просто, и поэтому был разработан несложный способ двоичного деления используемый в МП. 5 Как и в случае двоичного умножения, удобным оказывается использование операций сдвига. Представим делитель в дополнительном коде, чтобы обойтись сложением вместо вычитания. 1210 = 01100 дополнительный код - 10100 Теперь переходим к так называемому длинному двоичному делению: Будем вычитать из делимого делитель. О том, что делитель не укладывается в делимое, свидетельствует появление отрицательного результата вычитания (бит знака разности равен 1). Запишем в результат деления, частное - старший бит равный 0 и восстановим делимое. Если делитель укладывается в делимое (бит знака равен 0), то в частное запишем 1. Такая операция повторяется необходимое число раз, пока делимое не будет короче по длине делителя. При каждой операции происходит сдвиг остатка от делимого на один бит влево. Рассмотрим пример: 011001100 делимое 20410 + 10100 000001100 вычитаемое 1210 первый результат частное: 1.... Сдвинем результат 00001100 вторая операция: 00001100 + 10100 10101100 третья операция: 0001100 + 10100 1011100 частное: 10... частное: 100.. четвертая операция: 001100 + 10100 110100 пятая операция: 01100 + 10100 1 00000 остаток частное: 1000. частное: 10001 Если мы сдвинем сейчас остаток еще раз, то он станет короче делимого, значит, операция деления завершена. Итак: 10001 = 1710 На практике МП оперирует числами известной длины, поэтому и разрядность результата известна заранее. 6 Арифметика повышенной точности При работе с микропроцессором часто выясняется, что длина слов, которыми он оперирует, недостаточна для достижения определенной точности вычислений. Так восьмиразрядный МП позволяет использовать числа в диапазоне от -128 до +127,что конечно недостаточно. Используя два восьмибитовых слова, мы можем обрабатывать числа в диапазоне от -32768 до +32767. Для решения многих задач двойной точности вполне достаточно. Повышая точность представления числа, нам требуется больше времени и памяти для их обработки, а также не решается проблема представления очень больших и очень малых чисел. В настоящее время в составе программного обеспечения любой ЭВМ имеется пакет плавающей арифметики. Он оперирует с числами, представленными в виде чисел с плавающей точкой. Это достигается благодаря использованию представления десятичных дробей в нормализованном в виде, т.е. в виде мантиссы, значения которой простирается от 0,1 до 1 и порядка - показателя степени числа 10. Например: 50 = 0.5 * 102 Представление числа в форме с плавающей точкой в 8 - разрядном МП (можно изобразить следующим образом): 1 байт 2 байт 3 байт 4 байт \-------------------- мантисса (23 разряда) ------------------/ \ ------------ знак мантиссы \---- порядок (7 разрядов) \------ знак порядка Числа представленные в таком виде имеют достаточный диапазон, приемлемый для решения широкого круга задач по вычислениям и управлению объектами. Но, за все надо платить, в данном случае платить за точность приходится быстродействием. Плавающее число, представленное с двойной точностью, занимает 8 байт Вычисления в плавающей арифметике выполняются достаточно долго. Тип переменной символьная – 1 байт целая – 2 байта длинная целая – 4 байта “плавающая” – 4 байта “длинная плавающая” – 8 байт Диапазон представляемых значений положительного числа числа со знаком 0 ÷ 255 –128 ÷ 127 0 ÷ 65,535 –32,768 ÷ 32,767 0 ÷ 4,294,967,295 –2,147,483,648 ÷ 2,147,483,647 3.4 10 -38 ÷ 3.4 10 38 1.7 10 -308 ÷ 1.7 10 308 7