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