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

7vhp5slm  于 2022-11-13  发布在  其他
关注(0)|答案(4)|浏览(169)

学习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键,ASCII代码53将存储在 num1 中,但按ENTER键生成的换行符将继续执行下一个读取指令,它将存储在 num2 中。显然这不是我想要的。我希望用户键入一个数字,按Enter,键入另一个数字,然后按Enter。
我不完全确定如何以最简单的方式解决这个问题。
最愚蠢的想法是在 num1num2 之间放置一个“哑”读指令,它将捕获换行符(并且不对它做任何操作)。

c0vxltue

c0vxltue1#

这里有一个非常基本的阅读输入的方法,直到你得到你想要的数字。它将跳过除数字以外的任何内容。如果它提供了你想要的功能,这种方法是好的。如果你需要根据其他非数字输入的不同行为,那么你需要指定该行为。然后该行为也可以被编程。

; 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
    jl    get          ; Retry if the byte read is < '0'
    cmp   byte [ecx],0x39
    jg    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
ev7lccsx

ev7lccsx2#

通过stdin来禁用I_CANON是可行的,但这可能是一种“困难的方法”。如果讨厌的用户表现良好,那么使用两个字节的缓冲区并执行mov edx, 2也是可行的--要么清除第二个字节,要么忽略它。
有时候,讨厌的用户表现得并不好。处理“垃圾输入”或其他错误情况通常需要比“做工作”多得多的代码!要么处理它,要么满足于一个“通常”工作的程序。第二种选择可能对初学者来说已经足够了。
讨厌的用户可能只是按下“enter”而没有输入数字。在这种情况下,我们希望要么重新提示,要么打印“Sorry you didn 't like my program”并退出。或者他/她可能在按下“enter”之前输入了不止一个字符。这是潜在的危险!如果恶意用户输入“1 rm-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给你的第二个链接包括了我用来做这个的代码。我对它不是很满意(草率!),但它“有点工作”。无论如何,玩得开心!:)

pinkon5k

pinkon5k3#

你将不得不处理规范的禁用,原始键盘。这是linux如何管理输入控制台密码,例如不显示它。
下面很好地描述了执行此操作的程序集:
http://asm.sourceforge.net/articles/rawkb.html

vx6bjr1n

vx6bjr1n4#

这段代码在这里是有效的,只需要在一个数组中取输入,首先取2个字节,其中包括换行符,然后只取1个字节。在添加时忽略第二个字节。

SECTION .data

SECTION .bss
    
    num: resb 3

SECTION .text
    global _start

_start:
     nop
     mov eax, 3
     mov ebx, 0
     mov ecx, num
     mov edx, 2
     int 80h

     mov eax, 3
     mov ebx, 0
     mov ecx, num+2
     mov edx, 1
     int 80h

     add al, byte [num]
     add al, byte [num+2]
     mov byte [num], al

     mov eax, 4
     mov ebx, 1
     mov ecx, num
     mov edx, 1
     int 80h

     mov eax, 1
     mov ebx, 0
     int 80h
     nop
     nop

相关问题