FilipJ
FilipJ

Reputation: 125

Assembly: writing multiple lines into a buffer

I have a problem with my second ever program in Assembly. The task is to read multiple lines of text from a keyboard and write them down into a buffer (.comm). After an empty line is entered, program should echo in a loop each previously typed line of text. A limit for one line of text is 100 charcters. However, I get a "program received signal sigsegv segmentation fault / 0x00000000006000a5 in check ()" error message.

My idea is to create a buffer of size 5050 bytes. Each line of text can have at most 100 characters. Here is a visual structure of the buffer:

[First line     ][0][Second line      ][0][Short            ][0][Text             ][0]

UPDATE: According to Jester's reply (thanks!), I've slightly modified my idea for the program. I abandoned the idea of 100 bytes per line. I'll simply place them one after another, simply separating them with a special character (0). So a new structure of the buffer would be:

[First line of text][0][No matter how long it is][0][short][0]

However, I've got a problem with appending the special "0" character to the BUFFER in "add_separator" part. I also wonder if it's really necessary since we add the "\n" new line indicator into the BUFFER asswell?

Also, the part when I check if the entered line of code is empty never returns true (empty line state) so the program keeps loading and loading new lines. Did I miss anything?

Here is an updated bit of code:

SYSEXIT = 1
SYSREAD = 3
SYSWRITE = 4
STDOUT = 1
STDIN = 0
EXIT_SUCCESS = 0

.align 32

.data #data section

    .comm BUFFER, 5050  #my buffer of a size of 5050 bytes
    BUFFER_len = 5050


.global _start

_start:

mov $0,%esi

read:

    mov $SYSREAD, %eax
    mov $STDIN, %ebx
    mov BUFFER(%esi), %ecx
    mov $1, %edx
    int $0x80   

check:

    cmp $0, %eax        # check if entered line is empty
    je end          # if yes, end program

    lea BUFFER(%esi), %ecx  # move the latest character for comparison
    cmp '\n', %ecx      # check if it's a line end 
    inc %esi        # increment the iterator
    je end
    jmp read

end:

    mov $SYSWRITE, %eax
    mov $STDOUT, %ebx
    mov $BUFFER, %ecx
    mov $BUFFER_len, %edx

    int $0x80

    mov $SYSEXIT, %eax
    mov $EXIT_SUCCESS, %ebx
    int $0x80

Thanks in advance for any tips!

Filip

Upvotes: 1

Views: 1720

Answers (1)

Jester
Jester

Reputation: 58762

A few things:

  1. Trust me, you don't want to use esp as a general purpose register as a beginner
  2. The read system call will read at most as many bytes as you specify (in this case BUFFER_LEN) and it will return the number of bytes read. You should pass in 1 instead, so you can read char-by-char.
  3. Adding 100 for the next word (you really mean line, right?) isn't terribly useful, just append each character continuously since that's how you want to print them too.
  4. cmp '\n', %al would try to use the '\n' as an address, you want cmp $'\n', %al to use an immediate
  5. Learn to use a debugger to find your own mistakes
  6. using jg to jump over a jle is really unnecessary, just keep the jle and let the execution continue normally otherwise

Upvotes: 3

Related Questions