Информатика и информационные технологии: конспект лекций.
Арифметические действия над неупакованными ВСD-числами.
Сложение неупакованных ВСD-чисел.
Рассмотрим два случая сложения.
Пример.
Результат сложения не больше 9.
6 = 0000 0110.
+
3 = 0000 0011.
=
9 = 0000 1001.
Переноса из младшей тетрады в старшую нет. Результат правильный.
Пример.
Результат сложения больше 9:
06 = 0000 0110.
+
07 = 0000 0111.
=
13 = 0000 1101.
Мы получили уже не ВСD-число. Результат неправильный. Правильный результат в неупакованном ВСD-формате должен быть таким: 0000 0001 0000 0011 в двоичном представлении (или 13 в десятичном).
Проанализировав данную проблему при сложении ВСD-чисел (и подобные проблемы при выполнении других арифметических действий) и возможные пути ее решения, разработчики системы команд микропроцессора решили не вводить специальные команды для работы с ВСD-числами, а ввести несколько корректировочных команд.
Назначение этих команд – в корректировке результата работы обычных арифметических команд для случаев, когда операнды в них являются ВСD-числами.
В случае вычитания в примере 10 видно, что полученный результат нужно корректировать. Для коррекции операции сложения двух однозначных неупакованных ВСD-чисел в системе команд микропроцессора существует специальная команда – ааа (АSСII Аdjust fоr Аdditiоn) – коррекция результата сложения для представления в символьном виде.
Эта команда не имеет операндов. Она работает неявно только с регистром аl и анализирует значение его младшей тетрады:
1) если это значение меньше 9, то флаг сf сбрасывается в О и осуществляется переход к следующей команде;
2) если это значение больше 9, то выполняются следующие действия:
А) к содержимому младшей тетрады аl (но не к содержимому всего регистра!) прибавляется 6, тем самым значение десятичного результата корректируется в правильную сторону;
Б) флаг сf устанавливается в 1, тем самым фиксируется перенос в старший разряд, для того чтобы его можно было учесть в последующих действиях.
Так, в примере 10, предполагая, что значение суммы 0000 1101 находится в аl, после команды ааа в регистре будет 1101 + 0110 = 0011, т. е. двоичное 0000 0011 или десятичное 3, а флаг сf установится в 1, т. е. перенос запомнился в микропроцессоре. Далее программисту нужно будет использовать команду сложения аdс, которая учтет перенос из предыдущего разряда.
Вычитание неупакованных ВСD-чисел.
Ситуация здесь вполне аналогична сложению. Рассмотрим те же случаи.
Пример.
Результат вычитания не больше 9:
6 = 0000 0110.
-
3 = 0000 0011.
=
3 = 0000 0011.
Как видим, заема из старшей тетрады нет. Результат верный и корректировки не требует.
Пример.
Результат вычитания больше 9:
6 = 0000 0110.
-
7 = 0000 0111.
=
-1 = 1111 1111.
Вычитание проводится по правилам двоичной арифметики. Поэтому результат не является ВСD-числом.
Правильный результат в неупакованном ВСD-формате должен быть 9 (0000 1001 в двоичной системе счисления). При этом предполагается заем из старшего разряда, как при обычной команде вычитания, т. е. в случае с ВСD числами фактически должно быть выполнено вычитание 16 – 7. Таким образом, видно: как и в случае сложения, результат вычитания нужно корректировать. Для этого существует специальная команда – ааs (АSСII Аdjust fоr Substrасtiоn) – коррекция результата вычитания для представления в символьном виде.
Команда ааs также не имеет операндов и работает с регистром аl, анализируя его младшую тетраду следующим образом:
1) если ее значение меньше 9, то флаг сf сбрасывается в 0 и управление передается следующей команде;
2) если значение тетрады в аl больше 9, то команда ааs выполняет следующие действия:
А) из содержимого младшей тетрады регистра аl (заметьте – не из содержимого всего регистра) вычитает 6;
Б) обнуляет старшую тетраду регистра аl;
В) устанавливает флаг сf в 1, тем самым фиксируя воображаемый заем из старшего разряда.
Понятно, что команда ааs применяется вместе с основными командами вычитания sub и sbb. При этом команду sub есть смысл использовать только один раз, при вычитании самых младших цифр операндов, далее должна применяться команда sbb, которая будет учитывать возможный заем из старшего разряда.
Умножение неупакованных ВСD-чисел.
На примере сложения и вычитания неупакованных чисел стало понятно, что стандартных алгоритмов для выполнения этих действий над ВСD-числами нет и программист должен сам, исходя из требований к своей программе, реализовать эти операции.
Реализация двух оставшихся операций – умножения и деления – еще более сложна. В системе команд микропроцессора присутствуют только средства для производства умножения и деления одноразрядных неупакованных ВСD-чисел.
Для того чтобы умножать числа произвольной размерности, нужно реализовать процесс умножения самостоятельно, взяв за основу некоторый алгоритм умножения, например «в столбик».
Для того чтобы перемножить два одноразрядных ВСD-числа, необходимо:
1) поместить один из сомножителей в регистр АL (как того требует команда mul);
2) поместить второй операнд в регистр или память, отведя байт;
3) перемножить сомножители командой mul (результат, как и положено, будет в ах);
4) результат, конечно, получится в двоичном коде, поэтому его нужно скорректировать.
Для коррекции результата после умножения применяется специальная команда – ааm (АSСII Аdjust fоr Мultiрliсаtiоn) – коррекция результата умножения для представления в символьном виде.
Она не имеет операндов и работает с регистром АХ следующим образом:
1) делит аl на 10;
2) результат деления записывается так: частное в аl, остаток в аh. В результате после выполнения команды ааm в регистрах АL и аh находятся правильные двоично-десятичные цифры произведения двух цифр.
Перед окончанием обсуждения команды ааm необходимо отметить еще один вариант ее применения. Эту команду можно применять для преобразования двоичного числа в регистре АL в неупакованное ВСD-число, которое будет размещено в регистре ах: старшая цифра результата в аh, младшая – в аl. Понятно, что двоичное число должно быть в диапазоне 0… 99.
Деление неупакованных ВСD-чисел.
Процесс выполнения операции деления двух неупакованных ВСD-чисел несколько отличается от других, рассмотренных ранее операций с ними. Здесь также требуются действия по коррекции, но они должны осуществляться до основной операции, выполняющей непосредственно деление одного ВСD-числа на другое ВСD-число. Предварительно в регистре ах нужно получить две неупакованные ВСD-цифры делимого. Это делает программист удобным для него способом. Далее нужно выдать команду ааd – ааd (АSСII Аdjust fоr Divisiоn) – коррекция деления для представления в символьном виде.
Команда не имеет операндов и преобразует двузначное неупакованное ВСD-число в регистре ах в двоичное число. Это двоичное число впоследствии будет играть роль делимого в операции деления. Кроме преобразования, команда ааd помещает полученное двоичное число в регистр АL. Делимое, естественно, будет двоичным числом из диапазона 0… 99.
Алгоритм, по которому команда ааd осуществляет это преобразование, состоит в следующем:
1) умножить старшую цифру исходного ВСD-числа в ах (содержимое АН) на 10;
2) выполнить сложение АН + АL, результат которого (двоичное число) занести в АL;
3) обнулить содержимое АН.
Далее программисту нужно выдать обычную команду деления div для выполнения деления содержимого ах на одну ВСD-цифру, находящуюся в байтовом регистре или байтовой ячейке памяти.
Аналогично ааш, команде ааd можно найти и другое применение – использовать ее для перевода неупакованных ВСD-чисел из диапазона 0… 99 в их двоичный эквивалент.
Для деления чисел большей разрядности, так же как и в случае умножения, нужно реализовывать свой алгоритм, например «в столбик», либо найти более оптимальный путь.