【问题标题】:Checking if number inputted is between 0 and 9 Assembly [duplicate]检查输入的数字是否在 0 到 9 之间
【发布时间】:2021-02-12 00:45:12
【问题描述】:

我正在使用汇编编程,而且我对这门语言非常陌生。我在 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, 1
    mov rdi, 1
    mov rsi, 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, 1
    mov rdi, 1
    mov rsi, output1
    mov rdx, op1Len
    syscall
    ret

isOdd:
    cmp dword [input], 5
    jle lessThan
    call moreThan
    ret

lessThan:
    mov rax, 1
    mov rdi, 1
    mov rsi, output2
    mov rdx, op2Len
    syscall
    ret

moreThan:
    mov rax, 1
    mov rdi, 1
    mov rsi, output3
    mov rdx, op3Len
    syscall
    ret

goAgain:
    mov rax, 1
    mov rdi, 1
    mov rsi, confirm
    mov rdx, cLen
    syscall
    
    mov rax, 0
    mov rdi, 0
    mov rsi, 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

【问题讨论】:

  • 仔细阅读div的描述。您可能希望在使用之前将 edx 清零。
  • @NateEldredge 我认为我的程序在终止之前甚至没有达到checkEvenOdd。当我运行调试器时,它没有通过 checkNumZerocheckNumNine
  • 我会再检查一次。 “浮点异常”通常仅由您的程序没有任何浮点指令和整数除法溢出引起,它只有一个......
  • 无论如何检查偶数和奇数的更有效方法是test dword [input], 1 ; jz handleTrueEven
  • 顺便说一句,当我测试你的代码时,错误就在div 指令上。 (你的调试器可以告诉你。)

标签: linux assembly x86 user-input yasm


【解决方案1】:

为了解决这个问题,我们做了几处更改,如下所示。

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, 1
    mov rdi, 1
    mov rsi, 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, 1
    mov rdi, 1
    mov rsi, output1
    mov rdx, op1Len
    syscall
    call goAgain

isOdd:
    cmp byte [input], '5'
    jbe lessThan
    call moreThan
    call goAgain

lessThan:
    mov rax, 1
    mov rdi, 1
    mov rsi, output2
    mov rdx, op2Len
    syscall
    call goAgain

moreThan:
    mov rax, 1
    mov rdi, 1
    mov rsi, output3
    mov rdx, op3Len
    syscall
    ret

goAgain:
    mov rax, 1
    mov rdi, 1
    mov rsi, confirm
    mov rdx, cLen
    syscall
    
    mov rax, 0
    mov rdi, 0
    mov rsi, 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

【讨论】:

    猜你喜欢
    • 2021-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-12
    • 2021-11-15
    • 1970-01-01
    相关资源
    最近更新 更多