Додавання в ascii-форматі
Розглянемо процес додавання чисел 8 і 4 в ASCII-форматі: 38h+34h=6Ch. Отримана сума неправильна ні для ASCII-формату, ні для двійкового формату. Однак, ігноруючи ліву 6 і додавши 6 до правої .Ch: Ch + 6 =12h - одержимо правильний результат у десятковому форматі. Цей приклад злегка спрощено, але він добре демонструє процес, що виконує команда AAA при корекції.
Для прикладу, припустимо, що регістр AX містить 0038h, а регістр BX - 0034h. Числа 38 і 34 представляють два байти в ASCII форматі, які необхідно додати. Додавання й корекція кодується наступними командами:
ADD AL,BL ;Додати 34 і 38
AAA ;Корекція для додавання ASCII кодів.
Команда AAA перевіряє праву шістнадцяткову. цифру (4 біти) у регістрі AL. Якщо ця цифра знаходиться між Ah і Fh або прапорець AF дорівнює 1, то до регістра AL додається 6, а до регістра AH додається 1, прапорці AF і CF встановлюються в 1. У всіх випадках команда AAA встановлює в 0 ліву шіст. цифру в регістрі AL. Результат - у регістрі AX:
Після команди ADD: 006C
Після команди AAA: 0102
Для того, щоб отримати остаточне ASCII-значення, досить просто поставити трійки на місце лівих шістнадцяткових цифр:
OR AX,3030H ;Результат 3132
Все показане вище представляє додавання однобайтовых чисел. Додавання багатобайтних ASCII-чисел вимагає організації циклу, що виконує обробку справа наліво із врахуванням переносу. Приклад , показаний нижче, додає два трибайтні ASCII-числа в чотирибайтну суму.
.
TITLE ASCADD (COM) Додавання в ASCII-форматі
ASSUME CS:CODESG,DS:CODESG,SS:CODESG
ORG 100H
BEGIN: JMP SHORT MAIN
ASC1 DB '578' ; Елементи даних
ASC2 DB '694'
ASC3 DB '0000'
MAIN PROC NEAR
CLC
LEA SI,AASC1+2 ; Адреса ASCII-чисел
LEA DI,AASC2+2
LEA BX,AASC1+3
MOV CX,03 ; Виконати 3 цикли
A20:
MOV AH,00 ; Очистити регістр AH
MOV AL,[SI] ; Загрузить ASCII-байт
ADC AL,[DI] ; Додавання (з переносом)
AAA ; Корекція для ASCII
MOV [BX],AL ; Збереження суми
DEC SI
DEC DI
DEC BX
LOOP A20 ; Виконати 3 цикли
MOV [BX],AH ; Зберегти перенос
RET
MAIN ENDP
CODESG ENDS
END BEGIN
Зверніть увагу на наступне:
У програмі використається команда ADC, тому що будь-яке додавання може викликати перенос, що повинен бути доданий до наступного (лівого) байту.
Команда CLC установлює прапорець CF у нульовий стан.
Команда MOV очищає регістр AH у кожному циклі, тому що команда AAA може додати до нього одиницю. Команда ADC враховує пеpеноси. Зауважте, що використання команд XOR або SUB для обнулення регістра AH змінює прапорець CF.
Коли завершується кожний цикл, відбувається пересилання вмісту pегистра AH (00 або 01) у лівий байт суми.
В результаті виходить сума у вигляді 01020702. Програма не використає команду OR після команди AAA для занесення лівої трійки, тому що при цьому встановлюється прапорець CF, що змінить результат команди ADC. Одним з рішень у цьому випадку є збереження регістра прапорців за допомогою команди PUSHF, виконання команди OR, і, потім, відновлення регістра прапорців командою POPF:
ADC AL,[DI] ;Додавання з переносом
AAA ;Корекція для ASCII
PUSHF ;Збереження прапорців
OR AL,30H ;Запис лівої трійки
POPF ;Відновлення прапорців
MOV [BX],AL ;Збереження суми
Замість команд PUSHF і POPF можна використати команди LAHF (Load AH with Flags - завантаження прапорців у регістр AH) і SAHF (Store AH in Flag register - запис прапорців з регістра AH у регістр прапорців). Команда LAHF завантажує в регістр AH прапорці SF, ZF, AF, PF і CF; а команда SAHF записує вміст регістра AH у зазначені прапорці. У наведеному прикладі, однак, регістр AH уже використовується для арифметичних переповнень. Інший спосіб вставки трійок для одержання ASCII-кодів цифр - організувати обробку суми командою OR у циклі.