大会

时间:2017-03-09 15:06:13

标签: linux assembly x86

所以我必须做这样的练习:From STDIN take a string of text of any size, and then change every lowercase character to uppercase and vice versa and print it to a file or STDOUT。第二部分非常简单。但是现在我怎么能说一个单词,或任何长度的短语?例如,当我这样做时,我总是有一个长度为500左右的缓冲区,但现在它必须输入任何长度。我怎么能这样做?

我必须使用AT&T语法为32位Linux机器执行此操作。

这是我现在的代码:(不改为大写/小写)

SYSCALL32 = 0x80
READ = 3
WRITE = 4
STDIN = 0
STDOUT = 1
EXIT = 1
BUF_SIZE = 10


.data
    TEXT_SIZE: .long 0
    BUFOR: .space BUF_SIZE
    BUFOR1: .space BUF_SIZE

.globl _start
.text

_start:
reading:
    movl $READ, %eax
    movl $STDIN, %ebx
    movl $BUFOR, %ecx
    movl $BUF_SIZE, %edx
    int $SYSCALL32
    movl %eax, TEXT_SIZE


    movl $WRITE, %eax
    movl $STDOUT, %ebx
    movl $BUFOR, %ecx
    movl TEXT_SIZE, %edx
    int $SYSCALL32
    jmp reading

所以我在这里读取了长度为BUFOR的{​​{1}}的输入,但如果输入长度为260字节会怎样?

2 个答案:

答案 0 :(得分:1)

对此的简单解决方案是读取块,直到读取的最后一个字节为CR(按下输入):

SYSCALL32 = 0x80
READ = 3
WRITE = 4
STDIN = 0
STDOUT = 1
EXIT = 1
BUF_SIZE = 10

.data
TEXT_SIZE: .long 0
BUFOR: .space BUF_SIZE
BUFOR1: .space BUF_SIZE

.globl _start
.text

_start:
reading:
    movl $READ, %eax
    movl $STDIN, %ebx
    movl $BUFOR, %ecx
    movl $BUF_SIZE, %edx
    int $SYSCALL32
    movl %eax, TEXT_SIZE

    ; add the code for uppercase <-> lowercase here    

    movl $WRITE, %eax
    movl $STDOUT, %ebx
    movl $BUFOR, %ecx
    movl TEXT_SIZE, %edx
    int $SYSCALL32

    movl $BUFOR, %esi        ; last byte read = $BUFOR + 
    addl TEXT_SIZE, %esi     ; TEXT_SIZE
    mov -1(%esi), %ah        ; -1 
    cmp $0x0a, %ah           ; it if's not CR, keep on reading
    jnz reading

movl $EXIT, %eax             ; otherwise return to OS
int $SYSCALL32
ret

答案 1 :(得分:0)

明智的做法是读取固定大小的缓冲区,处理数据并将其写出来;只要read返回非零,就继续前进。这实际上不会以任何方式限制输入字符串长度,因为系统会提供一些缓冲区并阻止生成输入的进程写入,直到您的进程读取它为止。

在C中会出现类似的情况:

unsigned char buf[512];
int readsz = 0;
while(readsz = read(0, buf, sizeof(buf))) {
    /* ... invert case ... */
    write(1, buf, readsz);
}

如果您的分配确实需要一些莫名其妙的理由首先在内存中完全读取整个字符串,那么您必须使用来自libc的malloc动态分配内存,并且如果缓冲区已完成,则继续realloc - 循环的每次迭代(您也可以使用sbrk执行类似的操作,但它更复杂)。那将是这样的:

int capacity = 512;
int size = 0;
int readsz = 0;
char *buf = malloc(capacity);
if(buf==0) abort(); /* not enough memory */
while(readsz = read(0, buf+size, capacity-size)) {
    size+=readsz;
    if(size==capacity) {
        capacity *= 2;
        char *nbuf = realloc(buf, capacity);
        if(nbuf==0) abort(); /* not enough memory */
        buf = nbuf;
    }
}
/* now the valid data in buffer is size; do your thing and write it out */
/* ... invert case ... */
write(1, buf, size);

但同样,这是解决问题最愚蠢的方式。使用固定大小的缓冲区。

  

所以在这里我已经读取了长度为254的BUFOR的输入,但如果输入长度为260字节会怎样?

read将返回前254个字节,并将剩余的字节留在stdin缓冲区中;它将在您下次read来电时提供。只要read返回0以外的任何值,就必须循环。当你得到0时,表示标准输入在另一侧关闭,你可以停止阅读并退出。