繁体   English   中英

如何使用NASM Assembly忽略输入中的换行符?

[英]How do I ignore line breaks in input using NASM Assembly?

在学习NASM程序集时,我正在尝试制作一个程序,该程序可以读取两个一位数字输入。

我在.bss声明了两个变量:

num1 resb 1
num2 resb 1

然后,我要求用户这样写数字:

; Get number 1
mov EAX,3
mov EBX,1
mov ECX,num1
mov EDX,1
int 0x80

; Get number 2
mov EAX,3
mov EBX,1
mov ECX,num2
mov EDX,1
int 0x80

由于我只对一位数字输入感兴趣,因此将EDX设置为1 这样,无论用户键入什么,只有第一个字符都将存储在我的变量中(对吗?)。

问题在于,第一个字符之后的所有内容都将用于将来的读取。 如果键入5然后按ENTER5会很好地存储在num1 ,但是按ENTER生成的换行符将继续执行下一条读取指令,该指令将存储在num2 显然,这不是我想要的(我希望用户键入一个数字,然后按Enter,再键入另一个数字,然后按Enter)。

我不确定如何以最简单的方式解决此问题。

最愚蠢的想法是在num1num2之间放置一个“虚拟”读取指令,该指令将捕获换行符(并且不执行任何操作)。 这显然不好。

这是读取输入直到获得所需数字的一种非常基本的方法。 它将跳过数字以外的任何内容。 如果此方法可以提供所需的功能,则很好。 如果根据其他非数字输入需要不同的行为,则需要指定该行为。 然后,也可以对该行为进行编程。

    ; Get number 1
    mov   ECX,num1
    call  GetNumber

    ; Get number 2
    mov   ECX,num2
    call  GetNumber
    ...

GetNumber:
    pusha              ; save regs
get:
    mov   EAX,3        ; system call for reading a character
    mov   EBX,0        ; 0 is standard input
    mov   EDX,1        ; number of characters to read
    int   0x80         ; ECX has the buffer, passed into GetNumber
    cmp   byte [ecx],0x30
    jlt   get          ; Retry if the byte read is < '0'
    cmp   byte [ecx],0x39
    jgt   get          ; Retry if the byte read is > '9'

    ; At this point, if you want to just return an actual number,
    ; you could subtract '0' (0x30) off of the value read
    popa               ; restore regs
    ret

使用stdin进行I_CANON以禁用I_CANON将起作用,但可能是“艰难的方式”。 使用两个字节的缓冲区并执行mov edx, 2如果讨厌的用户行为良好mov edx, 2将起作用-清除第二个字节,或者只是忽略它。

有时,讨厌的用户表现不佳。 处理“垃圾输入”或其他错误情况通常比“完成工作”花费更多的代码! 要么处理它,要么对“通常”有效的程序感到满意。 第二种选择对于初学者可能就足够了。

讨厌的用户可能只是点击“输入”而没有输入数字。 在这种情况下,我们要重新提示,或者打印“对不起,您不喜欢我的程序”并退出。 或者他/她可能会在打“ enter”之前键入多个字符。 这是潜在的危险! 如果恶意用户键入“ 1rm -rf。”,则说明您已经清除了整个系统! Unix是强大的,并且像任何强大的工具一样,对于不熟练的用户而言也可能是危险的。

您可以尝试类似(警告:未经测试的代码!)...

 section .bss num1 resb 1 num2 resb 1 trashbin resb 1 section .text re_prompt: ; prompt for your number ; ... ; get the number (character representing the number!) mov ecx, num1 reread: mov edx, 1 mov ebx, 0 ; 1 will work, but 0 is stdin mov eax, 3 ; sys_read int 0x80 cmp byte [ecx], 10 ; linefeed jz got_it mov ecx, trashbin jmp reread got_it: cmp byte [num1], 10 ; user entered nothing? jz re_prompt ; or do something intelligent ; okay, we have a character in num1 ; may want to make sure it's a valid digit ; convert character to number now? ; carry on 

您可能需要弄弄它才能使它起作用。 我可能不应该发布未经测试的代码(您可能会那样尴尬!)。 对您来说,“像那样的事情”可能比摆弄termios容易。 Michael给您的第二个链接包括我为此使用的代码。 我对它不太满意(草率!),但是它“有点有用”。 无论哪种方式,玩得开心! :)

您将不得不处理标准的禁用原始键盘。 这就是linux如何在不显示示例的情况下管理输入控制台密码的方法。

此处很好地描述了执行此操作的程序集:

http://asm.sourceforge.net/articles/rawkb.html

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM