使用NASM中的scanf将非整数输入无符号整数,从而导致循环出现问题

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

每当我尝试在先前在循环中输入已接受的数字后,在我的scanf中输入一个字母或符号作为无符号整数,它会不断输入前一个数字,从而导致程序无限期运行。我该如何解决?这是我写的一个示例代码:

[bits 32]

global _main

extern _scanf
extern _printf

section .data
    prompt_number db "Please select a number. Enter 0 to escape. ", 0
    display_number db "You entered %u. ", 0
    number_fmt db "%u", 0
    number_input dd 0

section .bss

section .text
_main:
    push ebp
    mov ebp, esp
    and esp, 0xfffffff0

_Label:

    sub   esp, 16
    mov   dword[esp], prompt_number
    call  _printf
    add   esp, 16

    sub esp, 16
    mov dword[esp], number_fmt
    mov dword[esp+4], number_input
    call _scanf
    add esp, 16

    sub esp, 16
    mov dword[esp], display_number
    mov eax, [number_input]
    mov dword[esp+4], eax
    call _printf
    add esp, 16

    cmp dword[number_input], 0
    jne _Label

    mov   esp, ebp
    mov   eax, 1
    pop   ebp
ret 
nasm
1个回答
0
投票

这与scanf在这些情况下的运作方式有关,解决方案是从C语言中为Good way to flush scanf buffer when invalid entry entered提供一个建议的解决方案。

我的理解是,如果scanf无法将输入映射到格式字符串(在这种情况下尝试将任意字符转换为无符号整数),那么它会放弃但不会从输入缓冲区中删除任何内容。因此,在这种情况下,后续调用scanf只使用当前在缓冲区中的内容。

下面是移植第一个解决方案的快速尝试(使用getchar来使用缓冲区)。我无法保证其质量;这基本上是我第一次通过编程程序集运行:

[bits 32]

global _main

extern _getchar
extern _scanf
extern _printf

section .data
    prompt_number   db "Please select a number. Enter 0 to escape. ", 0
    display_number  db "You entered %u. ", 0
    scan_error      db "Error scanning input. ", 0
    number_fmt      db "%u", 0
    number_input    dd 0

section .bss

section .text
_main:
    push  ebp
    mov   ebp, esp
    and   esp, 0xfffffff0

_Label:

    sub   esp, 16
    mov   dword[esp], prompt_number
    call  _printf
    add   esp, 16

    sub   esp, 16
    mov   dword[esp], number_fmt
    mov   dword[esp+4], number_input
    call  _scanf
    add   esp, 16

    cmp   eax, 0
    jne    _ScanSuccess

_ScanError:
    sub   esp, 16
    mov   dword[esp], scan_error
    call  _printf
    add   esp, 16

_ScanErrorConsumeInput:
    sub   esp, 16
    call  _getchar
    add   esp, 16

    cmp   eax, -1   ; most common value indicating end-of-file
    je    _Label

    cmp   eax, 10   ; newline in ASCII
    je    _Label

    jmp   _ScanErrorConsumeInput

_ScanSuccess:
    sub   esp, 16
    mov   dword[esp], display_number
    mov   eax, [number_input]
    mov   dword[esp+4], eax
    call  _printf
    add   esp, 16

    cmp   dword[number_input], 0
    jne   _Label

_Return:
    mov   esp, ebp
    mov   eax, 1
    pop   ebp
    ret
© www.soinside.com 2019 - 2024. All rights reserved.