我是学习汇编语言的新手,正在尝试编写一个计算器,用户可以在其中输入 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)和结果:打印,但实际上并不显示数值计算
首先,错误:
done_parsing
用长度覆盖解析的数字print_result
在打印之前销毁数字print_result_buffer
打印的字符比需要的少 1 个字符(adjusying rsi based on parsed length)
,因为 rsi
会自动指向解析停止的位置buffer
接下来,错过的优化:
rip
相对寻址parse_number
不需要计算长度替代版本可能如下所示:
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