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.
MOV AH, 0MOV AL, '7' ; 37hADD AL, '5' ; AL = 6ChAAA ; AH = 1, AL = 2: unpacked 12OR AX, 3030h ; both digits -> charactersMOV BX, AXMOV DL, BHMOV AH, 02h ; DOS: print DLINT 21hMOV DL, BLMOV AH, 02hINT 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.