Читать «Assembler. Программирование на языке ассемблера IBM PC» онлайн - страница 177

Unknown Author

Такой анализ и преобразование суммы двух цифр двоично-десятичных чисел реализует следующая команда ПК:

ASCII-коррекция после сложения (ASCII adjust after addition): AAA

Эта команда ставится после команды сложения (например, ADD), которая сложила две десятичные цифры и записала сумму в регистр AL. Этот регистр является неявным операндом команды ААА, именно его содержимое она анализирует и корректирует. Например:

MOV AL,5

MOV AL,8    ;AL=13

AAA    ;CF=1, AL-03

С помощью данной команды можно следующим образом сложить два N-знач-ных неупакованных двоично-десятичных числа X и Y и записать сумму в Z (команда CLC обнуляет флаг переноса - см. разд. 14.2):

N EQU ...    ;N>0

X DB N DUP(?)

Y DB N DUP(?)

Z DB ?,N DUP(?)    ;первый байт - для переноса из старших цифр

;сложение неупакованных MOV CX,N MOV SI,N-1 CLC

SUM: MOV AL,X[SI]

ADC AL,Y[SI]

AAA

MOV Z[SI+1],AL DEC SI LOOP SUM MOV Z,0 ADC Z,0

2-10-ных чисел: Z:sX+Y

количество цифр в слагаемых

;индекс цифр слагаемых (справа налево)

;CF - перенос из младших цифр (вначале CF-0)

V*

;сложение цифр с учетом переноса из млад, цифр ;коррекция суммы и запись в CF переноса ;запись цифры суммы в Z ;к предыдущим цифрам слагаемых ;(команды DEC и LOOP не меняют CF)

;запись переноса из старших цифр

Теперь приведем полное описание действия команды ААА: если флаг дополнительного переноса AF равен 1 или если в 4 правых битах регистра AL находится величина от 10 до 15, тогда значение AL увеличивается на 6, флаг переноса CF получает значение 1 и значение регистра АН увеличивается на 1, иначе лишь обнуляется флаг CF; в любом случае 4 левых бита AL обнуляются. Отметим, что команда ААА меняет и другие флаги (например, флаг AF получает то же самое значение, что и флаг CF), однако это обычно не представляет интерес.'

Поясним действия команды ААА. Прежде всего отметим, что команда анализирует только 4 правых бита регистра AL, не обращая внимания на левые биты (причина этого будет указана ниже). Поэтому, если предыдущая команда сложения получила сумму больше 9, то команда ААА сможет распознать только суммы от 10 до 15. Для распознавания же сумм больше 15 привлекается флаг дополнительного переноса AF. Этот флаг меняется многими командами, однако интерес представляет только его изменение в командах сложения и вычитания: в командах сложения (ADD, ADC, INC) флаг AF получает значение 1, если при сложении 4 младших битов операндов получилась сумма больше 15 (если есть перенос из этих битов в более старшие биты), а в командах вычитания (SUB, SBB, DEC) флаг AF равен 1, если величина 4 младших битов первого операнда меньше величины таких же битов второго операнда (если был заем единицы для младших битов первого операнда). Так вот, по флагу AF команда ААА и распознает случай, когда сумма, полученная в предыдущей команде, больше 15. Итак, распознав, что сумма больше 9, команда ААА корректирует ее - добавляет к ней 6 и обнуляет левую половину регистра AL, что, как уже отмечалось, соответствует получению "правильной" цифры результата. Отметим, что левая половина AL обнуляется и в случае, когда сумма не превосходит 9, поэтому в регистре AL всегда остается только "правильная" цифра. Что же касается увеличения на 1 значения регистра АН, то это можно рассматривать как еще один способ фиксирования переноса (если вначале в АН был 0), но вообще-то такое изменение АН нужно для реализации умножения двоично-десятичных чисел (см. разд. 14.1.4).