打印出一个三位数的数字让我溢出

时间:2018-11-26 23:24:00

标签: assembly number-formatting x86-16

因此,我正在构建一个简单的8086程序,该程序允许用户输入2个2位数字和一个运算符并执行操作。如果运算符为“ +”,则将它们相加;如果运算符为“ *”,则将它们相乘并在屏幕上打印结果:

.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

问题出在打印上。如果数字小于100,则跳至仅输出两位数字。但是,如果大于等于100,则将数字除以100,将结果作为3位数中的第一个打印出来,并将其余部分放入AX中,以便可以继续打印出两位数。但是,当它继续时,我收到错误消息:

  

除法错误-溢出。
  手动处理此错误,
  在中断向量表中更改INT 0的地址。

有人可以帮忙吗?

1 个答案:

答案 0 :(得分:3)

Dvocifren:
    mov bx, 10
    div bx

当您的代码跳转到此处时,DX恰好为零(仅当请求的操作是乘法!),这对于WORD大小的除法非常有用

但是,当程序失败时,DX不再为零。 DL保存用DOS打印的字符。

通过使用BYTE大小的除法来解决它,或者写:

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

您可能没有意识到这一点,但是2个2位数字的乘积会导致 4位的结果,其中2个2位数字的总和只能产生 3位数的结果。结果,您的程序将在例如32 * 32 = 1024(4位数字!)


由于任务的要求,建议您到处使用BYTE大小的乘法和BYTE大小的除法。
接下来的代码可以显示4位数字的结果:

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