Lesson 19 of 48 intermediate

ASCII, BCD, Signed, and Unsigned Data

Same bits, different meanings — how the 8086 interprets binary patterns as text, decimal, or signed numbers

Open interactive version (quiz + challenge)

Real-world analogy

Binary data is like ink marks on paper — the same marks can be a letter, a number, or a secret code depending on who reads them. 01000001 is the letter 'A' if read as ASCII, the number 65 if read as unsigned decimal, or still 65 if read as signed (since the top bit is 0). The bits never change — only your interpretation does.

What is it?

The 8086 stores all data as binary patterns; the interpretation depends on the context. ASCII encodes characters (A=41h). BCD represents decimal digits in binary — unpacked (one digit per byte) or packed (two digits per byte) with DAA/DAS/AAA/AAS for correction. Unsigned integers use all bits for magnitude (0-255 for bytes). Signed integers use 2's complement (MSB = sign bit, -128 to +127 for bytes). CBW/CWD sign-extend for division.

Real-world relevance

BCD was essential in early computing for financial applications where decimal precision mattered — bank balances, tax calculations, and point-of-sale systems used BCD to avoid floating-point rounding errors. Modern SQL DECIMAL types and Java BigDecimal serve the same purpose. ASCII remains the foundation of all text processing, and 2's complement signed arithmetic is universal in every processor made today.

Key points

Code example

; Complete data representation examples

; === ASCII ===
msg     DB  'Score: ', 0     ; String with null terminator
digit   DB  '7'              ; Single ASCII digit

; Convert ASCII digit to number
MOV AL, [digit]     ; AL = 37h ('7')
SUB AL, '0'         ; AL = 07h (numeric 7)

; === PACKED BCD ADDITION ===
; Add decimal 49 + 38 = 87
MOV AL, 49h         ; Packed BCD 49
ADD AL, 38h         ; AL = 81h (49h + 38h)
DAA                 ; AL = 87h (valid packed BCD)

; === UNPACKED BCD with AAM ===
; Multiply BCD digits 7 * 8 = 56
MOV AL, 07h         ; Unpacked BCD 7
MOV BL, 08h         ; Unpacked BCD 8
MUL BL              ; AX = 0038h (7*8=56 in hex)
AAM                 ; AH = 05h, AL = 06h
                    ; Unpacked BCD result: 56

; === UNSIGNED vs SIGNED ===
MOV AL, 0C0h        ; Unsigned: 192, Signed: -64
MOV BL, 40h         ; Unsigned: 64,  Signed: +64

; Unsigned comparison
CMP AL, BL
JA  al_above         ; True! 192 > 64 unsigned

; Signed comparison
CMP AL, BL
JG  al_greater       ; False! -64 < 64 signed
JL  al_lesser        ; True!  -64 < 64 signed

; === SIGN EXTENSION for IDIV ===
MOV AX, -100        ; AX = FF9Ch
CWD                 ; DX:AX = FFFFFF9Ch = -100
MOV BX, 7
IDIV BX             ; AX = -14 (quotient), DX = -2 (remainder)

Line-by-line walkthrough

  1. 1. SUB AL, '0' — converts ASCII digit '7' (37h) to numeric value 7 (07h). Works because ASCII digits 0-9 are consecutive starting at 30h.
  2. 2. ADD AL, 38h after MOV AL, 49h — binary addition gives 81h, but we want BCD 87 (49+38=87). The result 81h is wrong in BCD because there is no 'digit' for 8 in the ones place.
  3. 3. DAA checks: low nibble of 81h is 1 (ok), high nibble is 8 (ok), but AF flag from the ADD indicates a low-nibble carry occurred. DAA adds 6 to correct: 81h + 06h = 87h.
  4. 4. MUL BL — unsigned multiply of AL(7) * BL(8) = 56 decimal, stored as 0038h in AX (binary, not BCD).
  5. 5. AAM — ASCII Adjust for Multiplication divides AL by 10: AH=quotient=5, AL=remainder=6. This converts binary 38h (56 decimal) to unpacked BCD 05:06.
  6. 6. CMP AL, BL with AL=C0h and BL=40h — the comparison sets flags based on C0h-40h=80h. CF=0 (no unsigned borrow) so JA is true. But SF=1 and OF=0 so the signed result is negative, making JL true.
  7. 7. CWD sign-extends AX=FF9Ch (which is -100) into DX:AX. Since bit 15 of AX is 1, DX becomes FFFFh.
  8. 8. IDIV BX — signed division of DX:AX (-100) by BX (7). Quotient in AX = -14 (FFF2h), remainder in DX = -2 (FFFEh).

Spot the bug

; Goal: Add packed BCD 85 + 29 = 114
MOV AL, 85h        ; Packed BCD 85
ADD AL, 29h        ; Binary: 85h + 29h = AEh
DAA                ; Should give 14h with CF=1
; Programmer stores result:
MOV [result], AL   ; Stores 14h
; But forgets about the carry!
; How does the programmer recover the '1' in 114?
Need a hint?
DAA sets the carry flag when the result exceeds 99 in BCD. Where does the hundreds digit come from?
Show answer
Bug: The result of 85 + 29 = 114, which is a 3-digit BCD number. DAA correctly adjusts AL to 14h and sets CF=1 to indicate the hundreds digit. But the programmer only stores AL (the low two BCD digits '14') and ignores CF. The hundreds digit '1' is lost! Fix: After DAA, check CF with ADC for a multi-byte BCD number, or store the carry separately: MOV [result], AL / MOV AL, 0 / ADC AL, 0 / MOV [result+1], AL. This stores 14h at result and 01h at result+1, representing BCD 114.

Explain like I'm 5

Imagine the number 11111111 written on a card. If you are playing the 'unsigned game,' that card is worth 255 points. If you are playing the 'signed game,' it means you owe 1 point (it is -1!). BCD is like writing each digit of a phone number in its own little box — 59 becomes box-5 and box-9 instead of converting to some weird binary number. ASCII is like giving every letter and number a secret agent code — 'A' is agent 65, '0' is agent 48.

Fun fact

The Intel 4004 — the world's first microprocessor — was designed specifically for a BCD calculator (the Busicom 141-PF). BCD arithmetic was so important in the 1970s that every major processor included BCD instructions. The x86 architecture carried DAA/DAS all the way to x86-64, where they were finally removed in 64-bit mode — over 30 years after they were first introduced!

Hands-on challenge

Write an 8086 assembly routine that: (1) Takes two 4-digit packed BCD numbers stored as 2 words each (e.g., decimal 9999 stored as 99h and 99h), (2) Adds them using ADD/ADC and DAA, (3) Stores the packed BCD result. Then write a separate routine that converts a signed 16-bit integer in AX to an ASCII string (handle negative numbers with a '-' prefix). Test with AX = -1234.

More resources

Open interactive version (quiz + challenge) ← Back to course: Microprocessor A–Z