1

学习 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

因为我只对一位数字输入感兴趣,所以我设置EDX1. 这样,无论用户键入什么,只有第一个字符会存储在我的变量中(对吗?)。

问题是第一个字符之后的所有内容都将用于将来的读取。如果你键入5然后按ENTER,5num1很好ENTER地存储在num2. 显然这不是我想要的(我希望用户输入一个数字,按 ENTER,输入另一个数字,然后按 ENTER)。

我不完全确定如何以最简单的方式解决这个问题。

最愚蠢的想法是在 and 之间放置一个“虚拟”读取指令num1num2它将捕获换行符(并且什么都不做)。这显然不好。

4

3 回答 3

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
于 2013-09-13T12:31:41.477 回答
1

使用标准输入来禁用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

您可能需要摆弄它才能使其正常工作。我可能不应该发布未经测试的代码(这样会让自己难堪!)。“类似的东西”对你来说可能比摆弄termios. 迈克尔给你的第二个链接包括我使用的代码。我对它不太满意(草率!),但它“有点工作”。不管怎样,玩得开心!:)

于 2013-09-13T12:52:46.583 回答
0

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

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

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

于 2013-09-13T10:14:39.327 回答