问题描述
我在用汇编编程,我对这门语言很陌生。我在 Ubuntu 中使用 yasm 进行编程。我应该从用户那里获取输入并判断他们的输入是偶数还是奇数。如果输入是奇数,我需要查看它是大于 5 还是小于 5。然后,在一切之后,我需要确保用户想要再次访问。我很确定我已经解决了,我只是在验证用户输入时遇到了麻烦。我试图确保他们输入一个从 0 到 9 的数字。
以下是我为我的程序编写的所有内容,我找不到哪里出错了。当我尝试运行它时,出现此错误:浮点异常(核心转储)
; Data section,declaring variables
section .data
output dd 'Enter a single digit between 0 and 9' ;1st output
nl db 0x0a
opLen equ $-output ;length of 1st output
Go equ 0x59 ;to check confirmation
go equ 0x79 ;to check confirmation
rem dd 0xffff ;empty remainder for modulo
output1 dd 'You entered an even number' ;output for even
op1Len equ $-output1 ;even output length
output2 dd 'You entered an odd number <= 5' ;output for odd less or equal to 5
op2Len equ $-output2 ;output length for first odd
output3 dd 'you entered an odd number > 5' ;output for odd more than 5
op3Len equ $-output3 ;output length for second odd
output4 dd '...what?...' ;output for if the thing entered is not a number
op4Len equ $-output4 ;else output length
confirm dd 'go again? (y/n): ' ;confirmation message
cLen equ $-confirm ;confirmation message length
divs dd 2
section .bss
input dd 0xffff ;for user input
again dd 0xffff ;for second user input
section .text
global _start
_start:
call printOutput ;prints first output
call getInput ;receives user input
call checkNumZero ;checks if number is greater than zero
call checkEvenOdd ;does the modulo operation on the number
cmp dword [rem],0 ;compares the remainder and 0
je handleTrueEven ;if remainder is zero,then the first message is outputted
call isOdd ;if the remainder isn't zero,it checks if it is greater or less than 5
call goAgain ;asks the user if they want to go again
printOutput:
mov rax,1
mov rdi,1
mov rsi,output
mov rdx,opLen
syscall
ret
getInput:
mov rax,0
mov rdi,0
mov rsi,input
mov rdx,0xffff
syscall
ret
checkNumZero:
cmp dword [input],'0'
jbe checkNumNine
call else
checkNumNine:
cmp dword [input],'9'
ja else
ret
else:
mov rax,output4
mov rdx,op4Len
syscall
ret
checkEvenOdd:
mov rax,0
mov eax,dword [input]
div dword [divs]
mov dword [rem],edx
ret
handleTrueEven:
mov rax,output1
mov rdx,op1Len
syscall
ret
isOdd:
cmp dword [input],5
jle lessthan
call moreThan
ret
lessthan:
mov rax,output2
mov rdx,op2Len
syscall
ret
moreThan:
mov rax,output3
mov rdx,op3Len
syscall
ret
goAgain:
mov rax,confirm
mov rdx,cLen
syscall
mov rax,again
mov rdx,0xffff
syscall
cmp dword [again],0x79
jne doneIf
cmp dword [again],0x59
jne doneIf
ret
doneIf:
mov rax,60
mov rdi,0
syscall
解决方法
为了解决这个问题,我们做了几处更改,如下所示。
section .data
output dd 'Enter a single digit between 0 and 9' ;1st output
nl db 0x0a
opLen equ $-output ;length of 1st output
rem dd 0xffff ;empty remainder for modulo
output1 dd 'You entered an even number' ;output for even
nl1 db 0x0a
op1Len equ $-output1 ;even output length
output2 dd 'You entered an odd number <= 5' ;output for odd less or equal to 5
nl2 db 0x0a
op2Len equ $-output2 ;output length for first odd
output3 dd 'you entered an odd number > 5' ;output for odd more than 5
nl3 db 0x0a
op3Len equ $-output3 ;output length for second odd
output4 dd '...what?...' ;output for if the thing entered is not a number
nl4 db 0x0a
op4Len equ $-output4 ;else output length
confirm dd 'go again? (y/n):' ;confirmation message
nl5 db 0x0a
cLen equ $-confirm ;confirmation message length
divs db 2
section .bss
input resb 0xff ;for user input
again resb 0xff ;for second user input
section .text
global _start
_start:
call printOutput ;prints first output
call getInput ;receives user input
call checkNumZero ;checks if number is greater than zero
call checkEvenOdd ;does the modulo operation on the number
cmp byte [rem],0 ;compares the remainder and 0
je handleTrueEven ;if remainder is zero,then the first message is outputted
call isOdd ;if the remainder isn't zero,it checks if it is greater or less than 5
;call goAgain asks the user if they want to go again
printOutput:
mov rax,1
mov rdi,1
mov rsi,output
mov rdx,opLen
syscall
ret
getInput:
mov rax,0
mov rdi,0
mov rsi,input
mov rdx,0xff
syscall
ret
checkNumZero:
cmp byte [input],0x30
jae checkNumNine
call else
checkNumNine:
cmp byte [input],0x39
ja else
ret
else:
mov rax,output4
mov rdx,op4Len
syscall
call goAgain
checkEvenOdd:
mov al,byte [input]
mov ah,0
div byte [divs]
mov byte [rem],ah
ret
handleTrueEven:
mov rax,output1
mov rdx,op1Len
syscall
call goAgain
isOdd:
cmp byte [input],'5'
jbe lessThan
call moreThan
call goAgain
lessThan:
mov rax,output2
mov rdx,op2Len
syscall
call goAgain
moreThan:
mov rax,output3
mov rdx,op3Len
syscall
ret
goAgain:
mov rax,confirm
mov rdx,cLen
syscall
mov rax,again
mov rdx,0xff
syscall
cmp byte [again],0x79
je _start
cmp byte [again],0x59
je _start
jmp doneIf
doneIf:
mov rax,60
mov rdi,0
syscall