David Daniels
David Daniels

Reputation: 131

Printing out a 3 digit number gives me overflow

So I'm building a simple 8086 program that allows the user to input 2 2-digit numbers and an operator and perform an operation. If the operator is "+" it adds them and if it's "*" it multiplies them and prints the result on screen:

.model small
.stack 100
.data

  x db ?
  y db ?
  rez dw ?

.code

    mov ax, data
    mov ds, ax
    mov es, ax

    mov ah, 1
    int 21h
    sub al, 48

    mov bl, 10
    mul bl

    mov x, al

    mov ah, 1
    int 21h
    sub al, 48

    add x, al

    mov ah, 1
    int 21h
    sub al, 48

    mov bl, 10
    mul bl

    mov y, al

    mov ah, 1
    int 21h
    sub al, 48

    add y, al

    mov ah, 1
    int 21h

    cmp al, 43
    jne Multiply

    mov al, x
    mov bl, y
    add al, bl
    mov ah, 0
    mov rez, ax
    jmp Print

Multiply:
    mov al, x
    mov ah, 0

    mov bl, y
    mov bh, 0
    mul bx

    mov rez, ax

Print:

    mov ax, rez
    cmp ax, 100
    jl Dvocifren
    mov bx, 100
    div bx
    mov cx, dx
    mov dl, al
    add dl, 48
    mov ah, 2
    int 21h
    mov ax, cx
    mov rez, ax

Dvocifren:
    mov bx, 10
    div bx

    mov cl, dl

    mov dl, al
    add dl, 48
    mov ah, 2
    int 21h

    mov dl, cl
    add dl, 48
    int 21h

The problem lies within the printing. If the number is less than 100 it jumps to only print out the two digits. However if it's greater of equal than 100 it divides the number by 100, prints out the result as the first of the 3 digits and puts the remainder in AX so it can continue with printing out the two digits. However when it continues I get the error message saying:

divide error - overflow.
to manually process this error,
change address of INT 0 in interrupt vector table.

Can anyone help?

Upvotes: 2

Views: 285

Answers (1)

Fifoernik
Fifoernik

Reputation: 9899

Dvocifren:
    mov bx, 10
    div bx

When your code jumps here, DX happens to be zero (Only if the requested operation was the multiplication!), which is good as you need it for this WORD-sized division.

BUT when your program falls through, DX is no longer zero. DL holds the character that you printed with DOS.

Solve it by using the BYTE-sized division instead, or else write:

Dvocifren:
    XOR DX, DX
    mov bx, 10
    div bx

You might not realize this but the multiplication of 2 2-digit numbers can lead to a 4-digit result, where the sum of 2 2-digit numbers can only produce a 3-digit result. As a consequence your program will fail on e.g. 32 * 32 = 1024 (4 digits!)


Because of what the task demands, I suggest you use BYTE-sized multiplication and BYTE-sized division everywhere.
Next code is able to display the 4-digits result:

Multiply:
 mov al, x
 mov bl, y
 mul bl
 mov rez, ax

Print:
 mov ax, rez
 cmp ax, 100
 jl Dvocifren

 mov bl, 100
 div bl
 mov cl, ah   ;Remainder [0,99]
 mov ch, 0
 push cx      ;Preserve the lowest 2 digits

 mov ah, 0    ;Quotient [0,98]
 mov bl, 10
 div bl
 mov cl, ah   ;Remainder [0,9]
 mov dl, al   ;Quotient  [0,9]
 add dl, 48
 mov ah, 02h
 int 21h
 mov dl, cl
 add dl, 48
 mov ah, 02h
 int 21h

 pop ax       ;Restore lowest 2 digits

Dvocifren:
 mov bl, 10
 div bl
 mov cl, ah   ;Remainder [0,9]
 mov dl, al   ;Quotient  [0,9]
 add dl, 48
 mov ah, 02h
 int 21h
 mov dl, cl
 add dl, 48
 mov ah, 02h
 int 21h

Upvotes: 3

Related Questions