如何测试以确保仅输入整数并确保在汇编中输入的长度为5个字节或更少?

时间:2016-07-17 15:44:48

标签: linux assembly nasm tty

如何测试以确保只输入一个整数并确保输入的长度在以下代码中是5个字节或更少?

我试图了解如何正确控制输入,以便在退出程序时不会将超过5个字节的输入输出到终端。

此外,我如何测试以确保只输入一个字符串,最后在最后一个场景中,只输入一个双精度数?

***根据x82和Peter C的指导更新了代码。我做了一些C disas,并且能够修改下面的原始代码。它仍然有一些缺陷,但你们都有很多帮助!当我输入超过5个整数字节时,我只是停留在它不会重新提示,因为它在输入字符数据时会继续将额外的字节数据转储到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 个答案:

答案 0 :(得分:0)

我只是回答问题的POSIX系统编程部分,一旦你知道你希望你的程序做什么,就可以让你做出正确的系统调用。使用gdb对其进行调试(请参阅标记wiki的底部以获取调试提示),并使用strace来跟踪系统调用。

您可能希望用C编写程序,而不是尝试同时学习asm和Unix系统调用API。用C语言写一些东西来测试这个想法,然后在asm中实现它。 (然后,当你遇到困难时,你可以查看编译器输出,看看编译器是如何做的。只要你仔细阅读并理解编译器生成的代码如何工作,你仍然在学习我建议使用-O2-O3作为asm实现的起点进行编译。至少-O1,绝对不是-O0。)。

  

我试图了解如何正确控制输入,以便在退出程序时不会将超过5个字节的输入输出到终端。

这只是一个POSIX语义问题,与asm无关。如果你在C中进行系统编程,调用read(2) system call,情况就会一样。你用mov eax,3 / int 0x80在asm中调用它,而不是像{C编译器输出那样call glibc包装器,但它是相同的系统调用。

如果程序退出时the terminal (tty)上有未读数据,shell会在检查输入时读取它。

在tty上运行的交互式shell中,您运行的程序(如./a.out/bin/cat)将其stdin连接到shell从中获取交互式输入的相同tty设备。因此,程序的stdin上的未读数据与shell将看到的未读数据相同。

如果您从文件重定向程序的输入,情况会有所不同。 (./a.out < my_file.txt)。然后你的程序将不会以tty的已打开文件描述符开头。它仍然可以open("/dev/tty")(这是一个“神奇的”符号链接,总是指控制tty)并清空在运行时输入的任何内容。

  

确保只输入一个整数,并确保输入长度为5个字节或更少,在以下代码中?

您无法控制输入内容。您可以检测您不喜欢的输入,并打印错误消息或您想要做的任何其他事情。

如果您希望输入字符在5个字节后停止回显到屏幕,则需要put the tty into raw mode(而不是默认的行缓冲“熟”模式)并手动执行回显,或禁用5个字节后回显。 (但后者不可靠。在禁用回声和用户输入第6个字节之间存在竞争条件(例如作为粘贴的一部分)。

RE:编辑

  

当我输入超过5个整数字节时,我只是坚持它不会像我输入字符数据那样重新提示,因为它继续将额外的字节数据转储到tty。

你打破了你的程序,因为如果你不喜欢你读过的数字,那么逻辑仍然围绕着重新read()一个字符来设计。但是您的read调用最多可读取5个字节。

正常的做法是一个大read,然后通过循环缓冲区中的字节来解析整行。因此,在.bss部分使用大缓冲区(如1024字节),并进行read系统调用。

除非您想提示用户输入另一行文字,否则不要进行另一次read系统调用。

答案 1 :(得分:0)

(由于您接受了此答案,我们会指出在TTY上使用read这个问题的实际答案是my other answer on this question。)

以下是您删除时我要发布的low-quality followup question的答案。

请注意,我说'#34;你可以在一个新问题中请求调试帮助&#34;而不是你应该在一个问题中提出3个不同的问题,并重新发布你的整个代码几乎没有改变,没有认真尝试解决你自己的问题。您仍然可以将新问题作为一个好的问题。

如果我没有引导你发布它,我可能不会回答它。欢迎来到StackOverflow,我很慷慨,因为你很新,不知道什么是一个好问题。

角色的常用术语&#39; 0&#39;通过&#39; 9&#39;是&#34;数字&#34;,不是&#34;整数&#34;。它更加具体。

  

确保只在缓冲区中输入整数

你不能。如果检测到这样的输入,你必须决定你想做什么。

  

需要帮助创建一个循环遍历的数组

你的缓冲区是一个字节数组。

你可以用

之类的东西循环它
    # 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.
  

确保1024缓冲区上的字符不发送数据到tty

如果您担心1024对于此玩具计划来说不一定足够大,请使用select(2)poll(2)检查是否还有更多输入如果没有阻止,请不要阻止地阅读。