2.Сложение и вычитание целых чисел
Кроме уже рассмотренной команды INC сложение осуществляют команды 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 результат нужно выбирать из регистра АХ. Аналогично можно складывать числа большей, чем 16 бит разрядности. Так, для сложения 32-битовых операндов (двойное слово) одно слагаемое можно поместить в РОН AX и BX, а второе - в DX и CX
SLAG1 DD 4bf8ff31h SLAG2 DD a5244986h
MOV AX, SLAG1; младшая часть MOV BX, SLAG1+2; старшая часть MOV CX, SLAG2 MOV DX, SLAG2+2 ADD AX, CX ADC BX, DX Команды ADD и ADC могут воздействовать на 6 флагов: - флаг переноса CF – устанавливается в 1, если результат сложения не помещается в операнде-приемнике, и противном случае CF=0; - флаг четности PF=1, если результат имеет четное число битов со значением 1, и противном случае PF=0; - вспомогательный флаг переноса AF=1, если результат сложения десятичных чисел требует коррекции, в противном случае он равен 0; - флаг нуля ZF=1, если результат сложения равен 0; - флаг знака SF=1, если сумма отрицательна (старший бит числа со знаком равен 1), в противном случае SF=0; - флаг переполнения OF=1, если сложение чисел одного знака приводит к результату, который превышает диапазон допустимых значений приемника в обратном коде, а сам приемник при этом меняет знак (рекомендую просмотреть параграф ”сложение двоичных чисел со знаком” на стр. 160-162 (учебник Юрова “Ассемблер”). Чтобы уяснить, как происходит сложение десятичных чисел, рассмотрим такой пример: сложим числа 26 и 55 в упакованном виде: 0010 0110 0101 0101 0111 1011 Полученный результат 7В не является десятичным упакованным числом. Поэтому результат должен быть скорректирован для представления в десятичном виде. Для этих целей разработчики Ассемблера предложили 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-числа в регистрах AL и BL DAA; и преобразовать результат в упакованное число Если результат превышает предельное значение для упакованных BCD-чисел, то DAA добавляет 1 к содержимому регистра AH и устанавливает в 1 флаг CF, в противном случае флаг устанавливается в 0. Замечание относительно остальных флагов для команды DAA такие же, как и для команды ААА. Как уже говорилось ранее, микропроцессор не имеет устройства вычитания, а имеет только устройство сложения (сумматор). Вычитание на таком устройстве осуществляется в 2 этапа: 1) меняется знак у вычитаемого - 2-го операнда или источника (иначе говоря, вычитаемое обращается); 2) складываются уменьшаемое и обращенное вычитаемое. Для обращения операнда в системе команд имеется самостоятельная команда NEG приемник. Эта команда вычитает значение операнда-приемника из 0 и, тем самым, формирует дополнительный код операнда (не забывайте, что дополнительный код числа в дополнительном коде будет являться модулем числа, или, иначе, обращение отрицательного числа даст число положительное). Установка флагов в этой команде осуществляется также, как и в команде вычитания. Команды вычитания SUB и SBB аналогичны соответствующим командам сложения, только при вычитании флаг CF понимается как признак заема. SUB приемник, источник– (приемник = приемник - источник) SBB приемник, источник – (приемник = приемник - источник – перенос_заем) Как и в случае сложения, команда SUB вычитает числа размером в байт или слово, а также младшие байты чисел повышенной точности. Совокупность команд SUB и SBB позволяет вычитать операнды повышенной точности (двойное слово), например:
per1 DD 4bf8ff31h per2 DD a5244986h
MOV AX, per1; младшая часть MOV BX, per1+2; старшая часть MOV CX, per2 MOV DX, per2+2 SUB AX, CX SBB BX, DX Здесь 32-битовое число из регистров CX и DX вычитается из 32-битового числа, помещенного в регистры AX и BX. Ограничение при вычитании – нельзя вычесть значение регистра или ячейки памяти из константы, поскольку, например, команда SUB 100, AL недопустима. Однако, если заменить недопустимую операцию 2-мя следующими NEG AL ADD AL, 100 то вычитание из непосредственного значения будет выполнено и результат получен в AL. Аналогично сложению, корректируются результаты вычитания при операциях с BCD-числами. Операция AAS корректирует результат вычитания неупакованной десятичной цифры из другой неупакованной десятичной цифры. Команда не имеет операндов и работает с регистром AL по следующему алгоритму: 1) если значение в регистре меньше или равно 9, то флаг CF устанавливается в 0 и управление передается следующей команде; 2) если значение в регистре AL больше 9, а) из содержимого младшей тетрады этого регистра вычитается 6, б) обнуляется старшая тетрада регистра AL; в) флаг CF устанавливается в 1, тем самым фиксируя наличие заема из предыдущего воображаемого разряда. Проблему в операциях с десятичными числами создают ситуации, когда уменьшаемое меньше вычитаемого. В этом случае результат является отрицательным, однако, для десятичных чисел нет представления отрицательных значений. Выявление и обработка таких ситуаций полностью ложится на плечи программиста, что свидетельствует о том, что алгоритмы арифметических действий в Ассемблере нужно разрабатывать более тщательно и подробнее, чем в языках программирования высокого уровня. Для упакованных BCD-чисел коррекцию результата вычитания производят командой DAS. Как и в предыдущей команде коррекции, результат предполагается в регистре AL, но теперь в обеих его тетрадах.
Дадим некоторые пояснения относительно арифметического переноса и переполнения. Перенос – это выход за пределы разрядной сетки, переполнение – неверный результат операции из-за недостаточной разрядности сетки. Рассмотрим на примерах.
В рассмотренных примерах первый столбец таблицы содержит двоичные значения складываемых переменных, следующие 2 столбца показывают результат, если складываемые переменные интерпретируются как беззнаковые числа (значения переменных переводятся в десятичную систему счисления и складываются), далее 4-ый и 5-ый столбец показывают результат, если эти же двоичные значения интерпретируются, как знаковые значения. Последние 6-ой и 7-ой столбцы таблицы показывают, как устанавливаются флаги переноса (CF) и переполнения (ОF) при выполнении операции суммирования (ADD). Проанализировав данные из таблицы, сделайте вывод: - если складываются беззнаковые переменные, о выходе результата за разрядную сетку свидетельствует установка в 1 флага переноса CF; - если складываются знаковые переменные, о неверном результате свидетельствует установка в 1 флага переполнения OF (обратитесь к описанию регистра флагов в лекции 4). Из рассмотренных примеров следует вывод, что нужно четко представлять себе величины подлежащих обработке чисел и выбирать числовые элементы данных (описания переменных в сегменте данных) подходящих типов. Особенно легко приводит к переполнению арифметические операции с байтовыми знаковыми переменными, поскольку диапазон представления чисел в таких переменных составляет от –128 до 127.
Воспользуйтесь поиском по сайту: ©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...
|