如何在x86 ASM中处理未知长度输入?

时间:2013-03-16 04:29:14

标签: assembly x86 gnu

所以我有大部分代码都可以工作,但是我无法弄清楚如何处理输入句子长度未知的事实。我是装配新手,这有点令人困惑。

(现在我已将它设置为好像长度已知为三个字符,但显然我需要更改它。)

.data       
input_msg:  .ascii "Enter a random sentence: "
input_msg_len:  .long 25
input_str:  .ascii  "???" # 3rd should get newline  
count:      .long 0 
newline:    .long 10    

.text               
.global _start          
_start:             

# prompt for input
    mov $4, %eax    # prompt for input
    mov $1, %ebx
    mov $input_msg, %ecx
    mov input_msg_len, %edx
    int $0x80
# get input
    mov $3, %eax    # 3 to request "read"
    mov $0, %ebx    # 0 is "console" (keyboard)
    mov $input_str, %ecx # input buffer addr
    mov $3, %edx    # number of symbols typed in
    int $0x80       # Go do the service!

again1:
    mov $input_str, %ecx    
    add count, %ecx # count is offset from input_str beginning

    mov $4, %eax    # to write
    mov $1, %ebx    # to console display
    mov $1, %edx    # 1 byte to write
    int $0x80   # Do it!

    push    %ecx        # push onto stack   

    incl    count   # increment count

    cmp $3, count   # compare lengths
    jnz again1     # jmp again if not 0 (no difference)

    mov $0, %edi    # use edi as loop counter

    mov $4, %eax    # print out msg
    mov $1, %ebx    # etc.
    mov $1, %edx    # length
    int $0x80       # OS, serve!

again2:     
    pop %ecx    

    mov $4, %eax    # print out msg
    mov $1, %ebx    # etc.
    mov $1, %edx    # length
    int $0x80       # OS, serve!        

    inc %edi    # increment edi 
    cmp count, %edi # compare lengths
    jnz again2  # jmp again if not 0 (no difference)

# print newline
    mov $4, %eax    # print out msg
    mov $1, %ebx    # etc.
    mov $newline, %ecx  # addr
    mov $1, %edx    # length
    int $0x80       # OS, serve!
# exit
    mov $1, %eax    # exit
    int $0x80       # OS, serve!    

基本上,我想知道的是如何让代码适用于任何句子,而不仅仅是3个字符?

2 个答案:

答案 0 :(得分:1)

你只需要为input_str分配一个更长的缓冲区,并读取有效读入的文本量,在read syscall之后的eax中找到。

换句话说,您需要决定接受的最大长度,并将代码更改为以下内容:
注意:可以分配这样的短字符串,静态,当然如果你需要一个大缓冲区(比如从文件中获取数据),你可以改为分配缓冲区动态< / em>的)。同样,对于键盘输入132可能是足够的。

...
input_str:  db  132 dup(?)  # 132 bytes buffer for input string
input_str_len: .long        # length of the string effectively read from user
...
# get input
    mov $3, %eax    # 3 to request "read"
    mov $0, %ebx    # 0 is "console" (keyboard)
    mov $input_str, %ecx # input buffer addr
    mov $131, %edx    # _Max_ number of bytes accepted in input_str
    int $0x80       # Go do the service!

    move %eax, $input_str_len    # save nb of bytes effectively read
...
    #you can then use input_str_len to control when to exit processing loop etc.

答案 1 :(得分:0)

嗯......你可以做一个%ebx = 0的sys_brk。这是你原来的“休息” - 保存它。将4k的倍数添加到该值并再次添加sys_brk。将sys_read放入该缓冲区。如果你读完整个4k(在sys_read之后的%eax中),再向你当前的“break”和sys_brk添加一些,然后再读一些......直到完成。这个“应该”在一个连续的缓冲区中为你提供一切......

更容易决定一些“最大”并且不要让他们输入更多!您可能想要“刷新缓冲区”。如您所知,sys_read(来自键盘)在看到换行符(0xA)之前不会返回。如果讨厌的用户键入了超过%edx个字符,则其余用户将保留在操作系统的缓冲区中。您可以在3字节缓冲区代码中看到这一点。输入“abcls”。我想你会发现退出后你的shell提示符会读取“ls”,并给你一个目录列表。没问题,但它可能是“rm”或有害的东西!当您的sys_read返回时,如果%eax小于%edx,您就完成了。如果%eax = %edx(它不会更多),如果缓冲区中的最后一个字符是LF(0xA),那么就完成了。如果没有,则sys_read进入虚拟缓冲区,直到获得该LF。这会使你的代码复杂化,但它“更安全”......

我可以在Nasm语法中尝试一个例子,但我认为我不会更好地尝试AT&amp; T ......:)