2017-03-09 22 views
0

所以我必须做这样的练习: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左右的缓冲区,但现在必须输入任意长度的输入。我怎样才能做到这一点?装配中未知尺寸的缓冲区

我必须在32位Linux机器的AT&T语法中执行此操作。

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

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 

所以在这里我读过的输入长度254BUFOR,但如果输入是什么样子的260个字节?

+0

你可以阅读的500个字节的块输入文件,观察一下你不需要知道整个输入即可开始工作。 – fuz

+0

好吧,我读了500字节,但接下来,我在哪里存储它或什么? – Frynio

+0

使用一个静态缓冲区,并按照需要读取文件结尾的次数进行加载。像'while(!eof()){num_read = read(500);处理(num_read); }' – Tommylee2k

回答

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 
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 -ing,如果缓冲区已完成(您也可以使用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字节,并保留其余的标准输入缓冲区;它会在您的下一个read呼叫中提供它们。只要read返回与0不同的任何东西,就必须循环。当您得到0时,意味着标准输入在另一端被关闭,您可以停止读取并退出。

+0

我不能使用C库,所以'malloc'不能使用 – Frynio

+0

@Frynio:你可以使用'brk'系统调用,但它更复杂,而且它很愚蠢;使用固定大小的缓冲区交替读写。 –

+0

我已经更新了有问题的代码,我想我实际上正在这样做,但现在它甚至可以读取30字节到10字节缓冲区中 – Frynio