ASM x86 (Intel syntax) calculator, why doesn't subtraction work?
05:44 20 Mar 2026

I am learning x86 assembly (Intel syntax) and writing a simple calculator as a .COM program in FreeDOS.

The program reads two digits and an operator from the keyboard and performs the operation.

Addition works correctly, but subtraction gives incorrect results (it behaves like addition or produces wrong values).

Example:

Input: 2-1=

Expected output: 1

Actual output: 3 (or incorrect value)

Program flow:

1. BX is initialized to 5000

2. Each key pressed is read using int 16h

3. The input is stored in memory using the `grd` routine

4. Memory layout:

5000 -> first operand

5002 -> operator

5004 -> second operand

5. When BX reaches 5004, execution jumps to `cn`

6. In `cn`, the operands are loaded into CL and DL

7. The operator is read from memory and compared with '+' (43) and '-' (45)

8. Depending on the result, execution jumps to addition or subtraction

9. The result is printed using int 10h

Limitations and design choices:

- Only single-digit operands (0–9) are supported

- Only addition and subtraction are implemented

- Input is read character by character

- No strict input validation is performed

- The result is printed as a single digit

To simplify memory handling, I store values in fixed memory addresses:

5000 -> first operand

5002 -> operator

5004 -> second operand

I increment BX by 2 after each input. I chose this approach to avoid overlapping values and make the memory layout easier to follow while learning low-level memory management.

I suspect the issue may be related to how ASCII values are handled or how the operator is stored.

Here is the code:

org 100h
mov bx, 5000

cun:
xor ah, ah
int 16h
call grd
add al, 48
cmp al, 81
je fin
mov ah, 0Eh
int 10h
jmp cun

cn:
pop bx
mov bx, 5000
mov cl, [bx]
add bx, 4
mov dl, [bx]
sub bx, 2
cmp byte [bx], 43
je sum
cmp byte [bx], 45
je res

sum:
add cl, dl
mov ah, 0Eh
mov al, cl
add al, 48
int 10h
jmp cun

res:
sub cl, dl
mov ah, 0Eh
mov al, cl
add al, 48
int 10h
jmp cun

grd:
sub al, 48
mov [bx], al
cmp bx, 5004
jge cn
add bx, 2
ret

fin:
int 20h
assembly x86