NASM 计算器 - 不会打印结果

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

我是学习汇编语言的新手,正在尝试编写一个计算器,用户可以在其中输入 2 个数字,并使用加法或减法来显示结果。我已经尝试了很多事情,但似乎无法找到我错在哪里!任何建议或解决方案将不胜感激。提前谢谢你:)

  section .data

        welcome db 0dh, 0ah, 0dh, 0ah, "**Hey, welcome to this calculator!**", 0dh, 0ah
        welcome_length equ $ - welcome
        msg_prompt db "Add your calculation (e.g., 24 + 6): ", 0
        msg_result db "Result: ", 0
        msg_newline db 10, 0    
        invalid_operator db "Invalid input, please use + or - for operations", 0

    section .bss
        buffer resb 32
        num1 resq 1 ; Number 1
        num2 resq 1 ; Number 2

    section .text
        global _start
    

    _start:
    ; Print the welcome message
        mov rsi, welcome
        mov rdx, welcome_length
        mov rax, 1
        mov rdi, 1 
        syscall

    
    ; Print the message prompt
        mov rsi, msg_prompt
        mov rdx, 37
        mov rax, 1
        mov rdi, 1
        syscall
    
    ; Read the input
        mov rsi, buffer
        mov rdx, 32
        mov rax, 0
        mov rdi, 0
        syscall

    ; Convert first number to an int
        mov rsi, buffer
        call parse_number
        mov [num1], rax

    ; Move to the operator (adjusying rsi based on parsed length)
    add rsi, rax
    call skip_spaces

    ; Check the operator
    movzx rbx, byte [rsi]
    cmp rbx, '+'
    je add_numbers
    cmp rbx, '-'
    je subtract_numbers

    ; Invalid operator - print error message
    mov rsi, invalid_operator
    mov rdx, 47
    mov rax, 1
    mov rdi, 1
    syscall
    jmp _exit

    ; Move to the 2nd
add_numbers:
    inc rsi
    call skip_spaces
    call parse_number
    mov [num2], rax

    ; Perform additiom
    mov rax, [num1]
    add rax, [num2]
    call print_result
    jmp _exit

    ; Move to the 2nd
subtract_numbers:
    inc rsi
    call skip_spaces
    call parse_number
    mov [num2], rax

    ; Perform subtraction
    mov rax, [num1]
    sub rax, [num2]
    call print_result
    jmp _exit

print_result:
    ; Printing the results
    mov rsi, msg_result
    mov rdx, 8
    mov rax, 1
    mov rdi, 1
    syscall

    ; Converting results to a string
    call print_number
    ret

parse_number:
    ; Convering a string to a number
    xor rax, rax
    mov rcx, 0

parse_loop:
    movzx rbx, byte [rsi]
    test rbx, rbx
    jz done_parsing
    cmp rbx, '0'
    jb done_parsing
    cmp rbx, '9'
    ja done_parsing
    sub rbx, '0'
    imul rax, rax, 10
    add rax, rbx
    inc rsi
    inc rcx
    jmp parse_loop
done_parsing:
    mov rax, rcx
    ret

print_number:
    ; Convert the number in rax  to ASCII in buffer and display
    mov rsi, buffer + 32
    mov rcx, 10
    add rsi, 1
    mov byte [rsi], 0

    ; If the number is 0, handle it seperately
    cmp rax, 0
    je print_zero

print_loop:
    xor rdx, rdx
    div rcx
    dec rsi
    add dl, '0'
    mov [rsi], dl
    test rax, rax
    jnz print_loop
    jmp print_result_buffer

print_zero:
    dec rsi
    mov byte [rsi], '0'
    jmp print_result_buffer
    
print_result_buffer:
    ; display result from buffer
    mov rdx, buffer + 32
    sub rdx, rsi
    mov rax, 1
    mov rdi, 1
    syscall
    ret

skip_spaces:
    ; skipping any spaces in the buffer
skip_space_loop:
    movzx rbx, byte [rsi]
    cmp rbx, ' ' 
    jne skip_done
    inc rsi
    jmp skip_space_loop
skip_done:
    ret

_exit:
    ; Exit the program
    mov rax, 60
    xor rdi, rdi
    syscall

我已经忘记了我尝试过的所有变化。输出确实允许用户输入方程式(例如 3 + 2)和结果:打印,但实际上并不显示数值计算

assembly error-handling printing nasm calculator
1个回答
0
投票

首先,错误:

  1. done_parsing
    用长度覆盖解析的数字
  2. print_result
    在打印之前销毁数字
  3. print_result_buffer
    打印的字符比需要的少 1 个字符
  4. 不需要
  5. (adjusying rsi based on parsed length)
    ,因为
    rsi
    会自动指向解析停止的位置
  6. 你在
    buffer
  7. 之外写了一个原本无用的 0

接下来,错过的优化:

  1. 您在很多地方不必要地使用了 64 位操作
  2. 不需要专门处理0,用0除以10就可以了
  3. 你应该使用
    rip
    相对寻址
  4. parse_number
    不需要计算长度
  5. 您可以在检查操作员之前读入第二个号码

替代版本可能如下所示:

default rel
section .data

        welcome db 0dh, 0ah, 0dh, 0ah, "**Hey, welcome to this calculator!**", 0dh, 0ah
        welcome_length equ $ - welcome
        msg_prompt db "Add your calculation (e.g., 24 + 6): ", 0
        msg_result db "Result: ", 0
        msg_newline db 10, 0    
        invalid_operator db "Invalid input, please use + or - for operations", 0

    section .bss
        buffer resb 32
        num1 resq 1 ; Number 1
        num2 resq 1 ; Number 2

    section .text
        global _start
    

    _start:
    ; Print the welcome message
        lea rsi, [welcome]
        mov edx, welcome_length
        mov eax, 1
        mov edi, 1 
        syscall

    ; Print the message prompt
        lea rsi, [msg_prompt]
        mov edx, 37
        mov eax, 1
        mov edi, 1
        syscall

    ; Read the input
        lea rsi, [buffer]
        mov edx, 32
        xor eax, eax
        xor edi, edi
        syscall

    ; Convert first number to an int
        call parse_number
        mov [num1], rax

    ; Move to the operator
    call skip_spaces

    ; Check the operator
    mov bl, [rsi]
    inc rsi
    call skip_spaces
    call parse_number
    mov [num2], rax
    cmp bl, '+'
    je add_numbers
    cmp bl, '-'
    je subtract_numbers

    ; Invalid operator - print error message
    lea rsi, [invalid_operator]
    mov edx, 47
    mov eax, 1
    mov edi, 1
    syscall
    jmp _exit

    ; Move to the 2nd
add_numbers:

    ; Perform additiom
    mov rax, [num1]
    add rax, [num2]
    call print_result
    jmp _exit

    ; Move to the 2nd
subtract_numbers:
    ; Perform subtraction
    mov rax, [num1]
    sub rax, [num2]
    call print_result
    jmp _exit

print_result:
    push rax
    ; Printing the results
    lea rsi, [msg_result]
    mov edx, 8
    mov eax, 1
    mov edi, 1
    syscall

    ; Converting results to a string
    pop rax
    jmp print_number

parse_number:
    ; Convering a string to a number
    xor eax, eax

parse_loop:
    movzx ecx, byte [rsi]
    sub cl, '0'
    cmp cl, '9'
    ja done_parsing
    imul rax, rax, 10
    add rax, rcx
    inc rsi
    jmp parse_loop
done_parsing:
    ret

print_number:
    ; Convert the number in rax  to ASCII in buffer and display
    lea rsi, [buffer + 32 + 1]
    mov ecx, 10

print_loop:
    xor edx, edx
    div rcx
    dec rsi
    add dl, '0'
    mov [rsi], dl
    test rax, rax
    jnz print_loop

print_result_buffer:
    ; display result from buffer
    lea rdx, [buffer + 32 + 1]
    sub rdx, rsi
    mov eax, 1
    mov edi, 1
    syscall
    ret

skip_spaces:
    ; skipping any spaces in the buffer
skip_space_loop:
    cmp byte [rsi], ' '
    jne skip_done
    inc rsi
    jmp skip_space_loop
skip_done:
    ret

_exit:
    ; Exit the program
    mov eax, 60
    xor edi, edi
    syscall
© www.soinside.com 2019 - 2024. All rights reserved.