编写一个简单的计算器(加、减、乘、除和对数)

问题描述 投票:0回答:1

我刚刚尝试创建一个计算器来简单地执行 5 种不同的操作(加、减、除和对数),但在 Turbo Assembler 中汇编代码时遇到问题。 任何想法如何解决这个问题?

我尝试执行上面的代码,但出现此错误 这是代码:

.model small
.data
    msg_input1 db 'Enter the first number: $'
    msg_input2 db 'Enter the second number: $'
    msg_operation db 'Choose operation (1: Add, 2: Multiply, 3: Subtract, 4: Divide, 5: Logarithm): $'
    msg_result db 'Result: $'
    msg_error db 'Error: Division by zero!$'

    num1 dw ?
    num2 dw ?
    result dw ?
    buffer db 6 dup(?) ; buffer to store result as a string

.code
main:
    mov ax, @data
    mov ds, ax

    ; Input the first number
    mov ah, 9
    mov dx, offset msg_input1
    int 21h

    call input_number
    mov num1, ax

    ; Input the second number
    mov ah, 9
    mov dx, offset msg_input2
    int 21h

    call input_number
    mov num2, ax

    ; Choose operation
    mov ah, 9
    mov dx, offset msg_operation
    int 21h

    mov ah, 1
    int 21h
    sub al, '0'

    ; Perform the selected operation
    cmp al, '1'
    je add_operation
    cmp al, '2'
    je multiply_operation
    cmp al, '3'
    je subtract_operation
    cmp al, '4'
    je divide_operation
    cmp al, '5'
    je logarithm_operation
    jmp invalid_operation

add_operation:
    mov ax, num1
    add ax, num2
    mov result, ax
    jmp display_result

multiply_operation:
    mov ax, num1
    call multiply_num2
    mov result, ax
    jmp display_result

subtract_operation:
    mov ax, num1
    sub ax, num2
    mov result, ax
    jmp display_result

divide_operation:
    cmp num2, 0
    je division_by_zero
    mov ax, num1
    cwd
    idiv num2
    mov result, ax
    jmp display_result

logarithm_operation:
    ; Your code for logarithm operation goes here

invalid_operation:
    ; Handle invalid operation
    jmp end_program

multiply_num2 proc
    ; Multiply AX by num2
    mov bx, num2
    mov cx, ax
    xor ax, ax
    multiply_loop:
        add ax, cx
        loop multiply_loop
    ret
multiply_num2 endp

division_by_zero:
    ; Display an error message
    mov ah, 9
    mov dx, offset msg_error
    int 21h
    jmp end_program

display_result proc
    ; Convert the result to a string
    mov ax, result
    mov cx, 10
    mov di, offset buffer + 4
    mov si, 0

convert_digit:
    xor dx, dx
    div cx
    add dl, '0'
    dec di
    mov [di], dl
    inc si
    test ax, ax
    jnz convert_digit

    ; Display the result message
    mov ah, 9
    mov dx, offset msg_result
    int 21h

    ; Display the result string
    mov ah, 9
    lea dx, [di]
    int 21h

    ; Display a new line
    mov ah, 2
    mov dl, 0Dh
    int 21h

    mov dl, 0Ah
    int 21h

    ret
display_result endp

input_number proc
    ; Initialize buffer
    mov si, offset buffer
    mov cx, 6
    mov di, 0
    rep stosb

    ; Read multiple characters
    mov cx, 6
    mov ah, 0
    input_loop:
        int 21h
        cmp al, 13 ; Check for Enter key
        je input_done
        mov [si], al
        inc si
        loop input_loop

    input_done:
        ; Convert buffer to number
        mov si, offset buffer
        mov cx, 6
        xor ax, ax
        convert_loop:
            mov al, [si]
            cmp al, '$' ; Check for end of buffer
            je convert_done
            sub al, '0'
            imul ax, 10
            add ax, dx
            add ax, al
            inc si
            loop convert_loop

    convert_done:
        ret
input_number endp

end_program:
    ; Exit program
    mov ah, 4Ch
    mov al, 0
    int 21h
end main

以下是错误:

汇编文件:Calc.asm 伊穆尔斧头,10 Error Calc.asm(175) 线上有多余字符 添加斧头,艾尔 错误 Calc.asm(177) 操作数类型不匹配

assembly calculator x86-16 tasm operands
1个回答
0
投票
Assembling file:   Calc.asm  
            imul ax, 10  
**Error** Calc.asm(175) Extra characters on line  
            add ax, al  
**Error** Calc.asm(177) Operand types do not match  

有关错误消息的说明,请参阅 Jester 的评论PeterCordes 的评论

接下来是对程序中错误的不完整总结。它至少应该允许您检查加法和减法运算。

  • input_number过程从缓冲区的错误初始化开始!

    rep stosb
    使用您错误地设置为零而不是buffer 的 DI。因此,您将覆盖 msg_input1 消息的前 6 个字节。您将用重复的“$”字符填充它,因为这是 DOS.PrintString 函数 09h 返回时留在 AL 寄存器中的内容。

  • 当您“读取多个字符”时,您使用了错误的功能编号!

    mov ah, 0
    选择退出程序的功能。您需要 DOS.GetKey Strike 函数 01h。

  • 由于我已经提到的第一个错误,“将缓冲区转换为数字”循环将徒劳地寻找“$”字符!
    并且由于 AL 寄存器(8 位)是 AX 寄存器(16 位)的一部分,因此您不能将计算出的数字保留在 AX 中,同时将下一个数字加载到 AL 中。乘法使用 AX(在 上),因此请为数字选择另一个寄存器。

在下面的代码中,6 字节缓冲区有可容纳 5 个十进制数字和 1 字节终止符 (13) 的空间。我确保这些数字实际上是有效的十进制数字。最多可以输入99999,所以还是有可能溢出的。

input_number proc
    mov  di, offset buffer
    mov  cx, 5
  input_loop:
    mov  ah, 01h
    int  21h
    cmp  al, 13            ; Check for Enter key
    je   input_done
    sub  al, '0'
    cmp  al, 10
    jnb  input_loop
    mov  [di], al          ; Store [0,9]
    inc  di
    loop input_loop
  input_done:
    mov  [di], al          ; Is terminator or harmless garbage
    mov  di, offset buffer
    mov  si, 10            ; CONST divider 10
    mov  cx, 5             ; Max 5 digits
    xor  bx, bx            ; Have BH=0
    xor  ax, ax            ; Result
  convert_loop:
    mov  bl, [di]
    cmp  bl, 13            ; Check for end of buffer
    je   convert_done
    imul si                ; AX * 10 -> DX:AX
    add  ax, bx            ; Plus newest digit
    inc  di
    loop convert_loop
  convert_done:
    ret
input_number endp
© www.soinside.com 2019 - 2024. All rights reserved.