Сложение и вычитание целых чисел
Мнемокоды и форматы арифметических команд приведены в приложении 2 [5]. Как видно из таблицы арифметических команд, сложение целых чисел осуществляется командами: ADD операнд1, операнд2 – (операнд1=операнд1+операнд2) или ADD приемник, источник– (приемник = приемник + источник) ADC операнд1, операнд2 – (операнд1=операнд1+операнд2 + значение cf) или ADC приемник, источник – (приемник = приемник + источник + перенос). Операндами могут быть как 8-ми битовые, так и 16-ти битовые двоичные числа. Если результат операции не помещается в приемник, микропроцессор фиксирует ситуацию переполнения, устанавливая в 1 флаг переноса. Действия программы в этой ситуации могут быть следующими: - прекратить выполнение программы по переполнению разрядной сетки; - увеличить разрядность операндов. Рассмотрим 2-ой вариант. Положим, складываются 8-миразрядные операнды из РОН AL и BL: ADD AL, BL; результат может превысить диапазон ; представления 8-ми разрядных чисел JNC M1; проверяем наличие переноса и при отсутствии ; переходим на М1 ADC AH, 0; расширяем разрядную сетку, добавив ; результат в РОН AH, теперь расширенный ; результат сложения помещается в 16-битовом РОН AX M1:. В этом фрагменте программы можно было опустить команду условного перехода и сразу после ADD выполнить команду ADC. Следует учесть, что после метки М1 результат нужно выбирать из регистра АХ. Команды ADD и ADC могут воздействовать на 6 флагов: - флаг переноса CF – CF=1, если результат сложения не помещается в операнде-приемнике, в противном случае CF=0; - флаг четности PF=1, если результат имеет четное число битов со значением 1, в противном случае PF=0; - вспомогательный флаг переноса AF=1, если результат сложения десятичных чисел требует коррекции; - флаг нуля ZF=1, если результат сложения равен 0; - флаг знака SF=1, если сумма отрицательна (старший бит числа со знаком равен 1), в противном случае SF=0; - флаг переполнения OF=1, если сложение чисел одного знака приводит к результату, который превышает диапазон допустимых значений приемника в дополнительном коде, а сам приемник при этом меняет знак. Специальных команд сложения десятичных чисел нет. Объясняется это тем, что микропроцессор все операнды интерпретирует как двоичные числа и складывает их по правилам сложения двоичных чисел. Чтобы уяснить, как происходит сложение десятичных чисел, рассмотрим такой пример: сложим числа 26 и 55 в упакованном виде: (0010 0110) + (0101 0101) = (0111 1011). Полученный результат не является десятичным упакованным числом. Поэтому результат должен быть скорректирован для представления в десятичном виде. Для этих целей разработчики ассемблера предложили 2 операции: ААА – корректировка результата для представления в кодах ASCII; DAA – корректировка результата для представления в упакованном десятичном формате. Обе команды не имеют операндов и по умолчанию корректируют значение из регистра AL. Команда ААА преобразует содержимое регистра AL в правильную неупакованную десятичную цифру в младших 4-х битах регистра, а старшие 4 бита заполняет нулями. Используется команда в контексте: ADD AL, BL; сложить неупакованные цифры, находящиеся в AAA; регистрах AL и BL и преобразовать результат в ; правильное десятичное число. Если результат операции превышает 9, то команда ААА добавляет 1 к содержимому регистра AH и устанавливает в 1 флаг CF, в противном случае флаг устанавливается в 0. Поскольку для дальнейшего анализа имеет значение только состояние флага CF, остальные флаги нужно считать неопределенными. Таким образом, после команды ААА значения флагов нельзя использовать для анализа в командах условного перехода. Команда DAA преобразует содержимое регистра AL в 2 правильные упакованные десятичные цифры. Она используется в следующем контексте: ADD AL, BL; сложить упакованные BCD-числа в регистрах DAA; AL и BL и преобразовать результат в упакованное ; число. Если результат превышает предельное значение для упакованных BCD-чисел, то DAA добавляет 1 к содержимому регистра AH и устанавливает в 1 флаг CF, в противном случае флаг устанавливается в 0. Замечания относительно остальных флагов для команды DAA такие же, как и для команды ААА. Поскольку микропроцессор не имеет устройства вычитания, а имеет только устройство сложения (сумматор), вычитание на таком устройстве осуществляется в 2 этапа: а) меняется знак у вычитаемого - второго операнда или источника (иначе говоря, вычитаемое обращается); б) складываются уменьшаемое и обращенное вычитаемое. Для обращения операнда в системе команд имеется самостоятельная команда NEG приемник. Эта команда вычитает значение операнда-приемника из нуля и, тем самым, формирует дополнительный код операнда (не забывайте, что дополнительный код числа в дополнительном коде будет являться модулем числа, или, иначе, обращение отрицательного числа даст число положительное). Установка флагов в этой команде осуществляется так же, как в команде сложения. Команды вычитания SUB и SBB аналогичны соответствующим командам сложения, только при вычитании флаг CF понимается как признак заема: SUB приемник, источник– (приемник = приемник - источник) SBB приемник, источник – (приемник = приемник - источник – перенос_заем). Ограничение при вычитании – нельзя вычесть значение регистра или ячейки памяти из константы, поскольку, например, команда SUB 100, AL недопустима. Однако, если заменить недопустимую операцию двумя следующими: NEG AL ADD AL, 100, то вычитание из непосредственного значения будет выполнено и результат получен в AL. Аналогично сложению, корректируются результаты вычитания при операциях с BCD-числами. Операция AAS корректирует результат вычитания неупакованной десятичной цифры из другой неупакованной десятичной цифры. Команда не имеет операндов и работает с регистром AL по следующему алгоритму: а) если значение в регистре меньше или равно 9, то флаг CF устанавливается в 0 и управление передается следующей команде; б) если значение в регистре AL больше 9, - из содержимого младшей тетрады этого регистра вычитается 6, - обнуляется старшая тетрада регистра AL; - флаг CF устанавливается в 1, тем самым фиксируя наличие заема из предыдущего воображаемого разряда. Проблему в операциях с десятичными числами создают ситуации, когда уменьшаемое меньше вычитаемого. В этом случае результат является отрицательным, однако, для десятичных чисел нет представления отрицательных значений. Выявление и обработка таких ситуаций полностью ложится на плечи программиста, что свидетельствует о том, что алгоритмы арифметических действий в ассемблере нужно разрабатывать более тщательно и подробнее, чем в языках программирования высокого уровня. Для упакованных BCD-чисел коррекцию результата вычитания производят командой DAS. Как и в предыдущей команде коррекции, результат предполагается в регистре AL, но теперь в обеих тетрадах.
|