How do I test to ensure only an integer is entered

2019-09-13 03:26发布

How do I test to ensure only an integer is entered and ensure length of input is 5 bytes or less in the following code?

I am trying to understand how to properly control input so that the input beyond 5 bytes is not outputted to the terminal upon exiting of the program.

In addition, how would I test to ensure only a string is entered and finally in the last scenario, only a double is entered?

*** Updated code based on x82 and Peter C's guidance. I did some C disas and was able to amend my original code below. It still has some flaws but you are both a great deal of help! I am just stuck on when more than 5 integer bytes are entered it wont re-prompt as it does when I enter in a character data as it continues to dump extra bytes data to tty.

SECTION .data                   ; initialized data section
promptInput db 'Enter Number: ', 0
lenPromptInput equ $ - promptInput
displayInput db 'Data Entered: ', 0
lenDisplayInput equ $ - lenDisplayInput

SECTION .bss                ; uninitialized data section
number resb 1024            ; allocate 1024 bytes for number variable

SECTION .text               ; code section
global _start               ; linker entry point

_start:
nop                         ; used for debugging

Read:
mov eax, 4                  ; specify sys_write call
mov ebx, 1                  ; specify stdout file descriptor
mov ecx, promptInput        ; display promptInput
mov edx, lenPromptInput     ; length of promptInput
int 0x80                    ; call sys_write

mov eax, 3                  ; specify sys_read call
mov ebx, 0                  ; specify stdin file descriptor
mov ecx, number             ; pass address of the buffer to read to
mov edx, 1024               ; specify sys_read to read 1024 bytes stdin
int 0x80                    ; call sys_read

cmp eax, 0                  ; examine sys_read return value in eax
je Exit                     ; je if end of file

cmp byte [number], 0x30     ; test input against numeric 0
jb Read                     ; jb if below 0 in ASCII chart
cmp byte [number], 0x39     ; test input against numeric 9
ja Read                     ; ja if above 9 in ASCII chart

Write:
mov eax, 4                  ; specify sys_write call
mov ebx, 1                  ; specify stdout file descriptor
mov ecx, displayInput       ; display displayInput
mov edx, lenDisplayInput    ; length of displayInput
int 0x80                    ; call sys_write    

mov eax, 4                  ; specify sys_write call
mov ebx, 1                  ; specify stdout file descriptor
mov ecx, number             ; pass address of the number to write
mov edx, 5                  ; pass number of numbers to write
int 0x80                    ; call sys_write

Exit:
mov eax, 1                  ; specific sys_exit call
mov ebx, 0                  ; return code 0 to OS
int 0x80                    ; call sys_exit

2条回答
混吃等死
2楼-- · 2019-09-13 04:11

(Since you accepted this answer, I'll point out that the actual answer to this question about using read on TTYs is my other answer on this question.)

Here's an answer to your low-quality followup question which I was about to post when you deleted it.

Note that I said "you can ask for debugging help in a new question", not that you should ask 3 different questions in one, and re-post your whole code barely changed with no serious attempt at solving your own problem. It's still up to you to make the new question a good question.

I probably wouldn't have answered it if I hadn't sort of led to you posting it in the first place. Welcome to StackOverflow, I'm being generous since you're new and don't know what's a good question yet.


The usual term for the characters '0' through '9' is "digit", not "integer". It's much more specific.

ensure only integers are inputted in the buffer

You can't. You have to decide what you want to do if you detect such input.

Need help creating an array to loop through

Your buffer is an array of bytes.

You can loop over it with something like

    # eax has the return value from the read system call, which you've checked is strictly greater than 0
    mov    esi, number        ; start pointer

scan_buffer:
    movzx  edx, byte [esi]
        # do something with the character in dl / edx
        ...

    inc    esi                ; move to the next character

    dec    eax
    jnz   scan_buffer         ; loop n times, where n = number of characters read by the system call.

ensure characters over the 1024 buffer do not send data to the tty

If you're worried that 1024 isn't necessarily big enough for this toy program, then use select(2) or poll(2) to check if there's more input to be read without blocking if there isn't.

查看更多
家丑人穷心不美
3楼-- · 2019-09-13 04:24

I'm just going to answer the POSIX systems programming part of the question, and leave it up to you to make the right system calls once you know what you want your program to do. Use gdb to debug it (see the bottom of the tag wiki for debug tips), and strace to trace system calls.

You might want to write your program in C instead of trying to learn asm and the Unix system call API at the same time. Write something in C to test the idea, and then implement it in asm. (Then you can look at the compiler output when you get stuck, to see how the compiler did things. As long as you carefully read and understand how the compiler-generated code works, you're still learning. I'd suggest compiling with -O2 or -O3 as a starting point for an asm implementation. At least -O1, definitely not -O0.).


I am trying to understand how to properly control input so that the input beyond 5 bytes is not outputted to the terminal upon exiting of the program.

This is just a POSIX semantics issue, nothing to do with asm. It would be the same if you were doing systems programming in C, calling the read(2) system call. You're calling it in asm with mov eax,3 / int 0x80, instead of calling the glibc wrapper like C compiler output would, but it's the same system call.

If there is unread data on the terminal (tty) when your program exits, the shell will read it when it checks for input.

In an interactive shell running on a tty, programs you run (like ./a.out or /bin/cat) have their stdin connected to the same tty device that the shell takes interactive input from. So unread data on your program's stdin is the same thing as unread data that the shell will see.

Things are different if you redirected your program's input from a file. (./a.out < my_file.txt). Then your program won't start with an already-open file descriptor for the tty. It could still open("/dev/tty") (which is a "magic" symlink that always refers to the controlling tty) and vacuum up anything that was typed while it was running.


ensure only an integer is entered and ensure length of input is 5 bytes or less in the following code?

You can't control what your input will be. You can detect input you don't like, and print an error message or anything else you want to do.

If you want input characters to stop echoing to the screen after 5 bytes, you'd need to put the tty into raw mode (instead of the default line-buffered "cooked" mode) and either do the echo manually, or disable echo after 5 bytes. (The latter wouldn't be reliable, though. There'd be a race condition between disabling echo and the user typing a 6th byte (e.g. as part of a paste).


RE: edit

I am just stuck on when more than 5 integer bytes are entered it wont re-prompt as it does when I enter in a character data as it continues to dump extra bytes data to tty.

You broke your program, because the logic is still designed around re-read()ing a character if you don't like the digit you read. But your read call reads up to 5 bytes.

The normal thing to do is one big read and then parse the whole line by looping over the bytes in the buffer. So use a big buffer (like 1024 bytes) in the .bss section, and make a read system call.

Don't make another read system call unless you want to prompt the user to enter another line of text.

查看更多
登录 后发表回答