AAA fixes up the result of adding two unpacked BCD digits, that is, numbers 0–9 held one per byte. ASCII digits ('0'..'9', 30h..39h) also count, because their low four bits are the digit. Add the two digits into AL with ADD, then AAA turns AL back into a single decimal digit and moves the decimal carry into AH.

Exactly what it does

If the low four bits of AL are greater than 9, or AF is 1, then AAA adds 6 to AL, adds 1 to AH, and sets AF and CF to 1. Otherwise it clears AF and CF. In both cases it then clears the upper four bits of AL, so AL ends up 0–9. OF, SF, ZF and PF are undefined.

AF matters for sums from 16 to 18: 9 + 9 = 18 = 12h leaves a 2 in the low four bits, which looks fine, but the carry out of bit 3 set AF, so AAA still corrects it to AH + 1 and AL = 8.

Prints 12.
MOV AH, 0
MOV AL, '7' ; 37h
ADD AL, '5' ; AL = 6Ch
AAA ; AH = 1, AL = 2: unpacked 12
OR AX, 3030h ; both digits -> characters
MOV BX, AX
MOV DL, BH
MOV AH, 02h ; DOS: print DL
INT 21h
MOV DL, BL
MOV AH, 02h
INT 21h

Multi-digit sums

To add two long numbers stored as strings of digits, work from the last digit to the first: add the two digits plus the carry with ADC, then AAA, store AL (with OR AL, 30h if you want ASCII back), and keep going; CF from AAA carries into the next column. Since AAA clears the high bits of AL, the 30h of ASCII digits does no harm on the way in, but must be put back on the way out.

Pitfalls

AAA only works on AL, after an addition whose result is in AL. It does not look at AL's upper four bits at all, so it cannot fix a sum of two packed BCD bytes; that is DAA's job. Clear or set AH before, since AAA adds to it.

Later CPUs

Later processors add 106h to AX as a whole instead of adding 6 to AL and 1 to AH separately; the two differ only when AL is FAh or more, which a sum of two digits never is. In 64-bit mode AAA is not available.