学习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
之间放置一个“虚拟”读取指令,它将捕获换行符(并且不执行任何操作)。这显然不太好。
答案 0 :(得分:1)
这是一种非常基本的阅读输入方式,直到你得到你想要的数字。它会跳过任何数字而不是数字。如果它提供您想要的功能,这种方法很好。如果根据其他非数字输入需要不同的行为,则需要指定该行为。然后也可以编程这种行为。
; 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
答案 1 :(得分:1)
干预stdin以禁用I_CANON
将起作用,但可能是“艰难的方式”。如果讨厌的用户表现良好,使用双字节缓冲区并执行mov edx, 2
将会有效 - 要么清除第二个字节,要么忽略它。
有时候讨厌的用户表现不佳。处理“垃圾输入”或其他错误条件通常需要比“做工作”更多的代码!要么处理它,要么对“通常”工作的程序感到满意。对于初学者来说,第二种选择可能就足够了。
讨厌的用户可能只是点击“输入”而不输入数字。在这种情况下,我们要么重新提示,要么打印“抱歉,你不喜欢我的程序”并退出。或者他/她可能会在点击“输入”之前输入多个字符。这有潜在危险!如果恶意用户键入“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
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
您可能需要摆弄它才能使其发挥作用。我可能不应该发布未经测试的代码(你可以这样尴尬!)。 “这样的事情”可能比摆弄更容易。迈克尔给你的第二个链接包括我用于此的代码。我对它不太满意(马虎!),但它“有点儿”。无论哪种方式,玩得开心! :)
答案 2 :(得分:0)
你将不得不处理规范的禁用原始键盘。 这就是linux如何管理输入控制台密码而不显示它。
这里很好地描述了执行此操作的程序集: