Это связано с тем, как scanf
работает в этих условиях, и решение состоит в том, чтобы портировать одно из предложенных решений для Хороший способ очистить буфер scanf, когда введена неверная запись из C.
Насколько я понимаю, если 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