'NASM - Get a sub-string by cycling a big text

I have this homework in which i have some words from a txt file and, depending on a random number, i must take out one of the words inside, txt file looks like this:

,author0,fear0,dance0,money0,bottle0,pillow0

As you can see there is a ',' before and a '0' after each word. I already have the random number and the import of the file content done and successful, however what i am trying to do to for extract the sub-string and therefore the word, is: looping the whole text content, when it reaches a ',' it compares to know if the counter of ',' appearances is the same as the random number and by then, save the next characters in the buffer variable until finding a '0' so it can return to the start function. I have this code by far:

%include macros.inc ;macros and definition of system calls

%include random.asm ;where the random number is created

section .data

filename: dq "txt/low.txt",10

counter: db 0 ;counts the traveled spaces to know if equals random

random: db 0

section .bss

text resq 18 ;stores all the content in txt file

buffer resb 18;saves the substring looked from text, supposed to be a word

section .text

global _start

_start:

call fileReadingLow ;saves txt file content in 'text' variable

call generateRandomNumber ;saves a random number between 0-9 in 'random'

mov eax,text ;for looping characters in text

mov ecx,48 ;amount of characters in text

call loopWord

print buffer ;macro from macros.inc

exit ;macro

fileReadingLow:

;Open the file

mov rax, SYS_OPEN

mov rdi, filename

mov rsi, O_RDONLY

mov rdx,0

syscall

;Read from file

push rax

mov rdi, rax

mov rax, SYS_READ

mov rsi, text

mov rdx, 128

syscall

;Close file

mov rax, SYS_CLOSE

pop rdi

syscall

ret

loopWord:

push rcx

cmp byte[eax],',' ;if character is a comma

je checkRandom

inc eax

pop rcx

loop checkRandom

checkRandom:

mov ebx,[counter]

cmp ebx,[random]

je getWord ;compare if random equals counter of appearances

inc ebx ;increments counter

mov [counter],ebx

pop rcx ;pop cause it does not reaches this line in loopWord

inc rcx ;same reason as above

jmp loopWord

getWord: ;loop the following characters for adding them to buffer

cmp byte[eax],'0' ;suppossedly last char from the word

je RETURN

mov dl,byte[eax] ;char from text in dl

mov [byte+1],dl ;add the char to buffer

inc eax

jmp getWord

RETURN:

pop rcx

ret

My main problem is that i do not know how to append chars consecutively in my buffer variable, by far it only contains the last character of each word. If someone would know how to do this would solve everything.



Solution 1:[1]

There's more than one error:

,author0,fear0,dance0,money0,bottle0,pillow0

The file has 44 bytes, but your program uses the number 48

filename: dq "txt/low.txt",10

The correct way to write this is filename db "txt/low.txt", 0 using the db directive.

counter: db 0
random: db 0

These are defined as bytes, but your program reads and writes these as dwords!


My main problem is that i do not know how to append chars consecutively in my buffer variable, by far it only contains the last character of each word. If someone would know how to do this would solve everything.

The loopWord code is wrong in many places. I don't see how it can be salvaged!

Let's start by writing a loop that just traverses the file held in text.

; IN (rax,rcx)
loopWord:
  mov  dl, [rax]        ; Fetch current character
  ...
  inc  rax              ; Move pointer
  dec  rcx              ; Decrement counter
  jnz  loopWord         ; Continue until exhausted
  ret

Then we'll start counting commas:

; IN (rax,rcx)
loopWord:
  mov  dl, [rax]
  cmp  dl, ','
  jne  .cont            ; Skip if not comma
  sub  byte [random], 1 ; Produces CF=1 only if random was 0 before
  jb   .found
.cont:
  inc  rax
  dec  rcx
  jnz  loopWord
  ret
.found:
  ...

Once found the entry, we will copy it to the buffer.

; IN (rax,rcx)
loopWord:
  mov  dl, [rax]
  cmp  dl, ','
  jne  .cont
  sub  byte [random], 1
  jnb  .found
.cont:
  inc  rax
  dec  rcx
  jnz  loopWord
  ret
.found:
  mov  ebx, buffer
.next:
  mov  dl, [rax]        ; Read next character from SOURCE
  mov  [rbx], dl        ; Write next character in DESTINATION
  inc  rax              ; Move SOURCE pointer
  inc  rbx              ; Move DESTINATION pointer
  cmp  dl, '0'          ; Continue until '0' was read and written
  jne  .next
  ret

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Sep Roland