[英]How do i read single character input from keyboard using nasm (assembly) under ubuntu?
[英]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
然后按ENTER
, 5
会很好地存储在num1
,但是按ENTER
生成的换行符将继续执行下一条读取指令,该指令将存储在num2
。 显然,这不是我想要的(我希望用户键入一个数字,然后按Enter,再键入另一个数字,然后按Enter)。
我不确定如何以最简单的方式解决此问题。
最愚蠢的想法是在num1
和num2
之间放置一个“虚拟”读取指令,该指令将捕获换行符(并且不执行任何操作)。 这显然不好。
这是读取输入直到获得所需数字的一种非常基本的方法。 它将跳过数字以外的任何内容。 如果此方法可以提供所需的功能,则很好。 如果根据其他非数字输入需要不同的行为,则需要指定该行为。 然后,也可以对该行为进行编程。
; 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如何在不显示示例的情况下管理输入控制台密码的方法。
此处很好地描述了执行此操作的程序集:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.