News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

How do you read a string into an array?

Started by bcddd214, April 27, 2011, 02:53:41 AM

Previous topic - Next topic

hutch--

There is some virtue in using an array of pointers, you can leave it in memory without having to protect the stack and work on it in any oder you want later. Transient techniques like pushing an popping the stack will do the job but unless you store it somewhere you have to process the data immediately or you lose it. Now RE: loading unknown sized data of any size up to very large, you can write a more complex routine that does a memory probe each iteration to see if the added data goes past the end of the current allocated memory, if it does you reallocate the buffer to a larger size so it handles the extra data.

Its messy to code correctly but is extendable to the final limit of memory automatically.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

dedndave

the real beauty is...
it's assembly language
you can do it which ever way is best for a given situation

RuiLoureiro

#17
Quote
  How do you read a string into an array
        1. First we must define MAXLENGTH=255  (for example, may be 1000...)
           and last index in the array MAXINDEX=2000 (for 2000 strings)
           Do MAXLENGTH1=MAXLENGTH+1 (for null terminated strings)
           
        2. Alloc buffer to that array (MyStrArray)
           Alloc buffer to READ each string from keyb (AnyString)
           
;-------------
MAXLENGTH   equ 255
MAXLENGTH1  equ MAXLENGTH+1
MAXINDEX    equ 2000

.DATA   
        AnyString   db MAXLENGTH1 + 5 dup (?)  
        MyStrArray  db MAXLENGTH1 * MAXINDEX dup (?)    
;-------------

        3. Read the string to AnyString
       
        4. Call your proc to put that string inside MyStrArray in the
           position N (index N - valid indexes are 1 to MAXINDEX, 0 is invalid ok)

           To calculate the position we do (when index N is in EBX)
           
           mov      edi, offset MyStrArray
           mov      eax, MAXLENGTH1
           sub      ebx, 1                                ; ebx=0 is invalid
           mul      ebx
           add      edi, eax                ; EDI points to MyStrArray[N]
;--------------------------------------------------
If we choose MAXLENGTH = 63

           To calculate the position we do (when index N is in EBX)

           mov      edi, offset MyStrArray
           sub      ebx, 1
           shl      ebx, 6                  ; multiply ebx by 64
           add      edi, ebx                ; EDI points to MyStrArray[N]

mineiro


        TITLE   Random
        INCLUDE Irvine32.inc

        .DATA?
MAX = 80                     ;max chars allowed to read
stringIn BYTE MAX+1 DUP (?)  ;room for null
ARRAY_SIZE = 10000
MyArray byte ARRAY_SIZE dup(?) ;creates an empty array of ARRAY_SIZE bytes

        .DATA

ARRAY_LENGHT DWORD 0
PTR_ROOM DWORD 0
intro byte "press enter in a blank line to exit this loop, while this",0dh,0ah,00h
intro1 byte "now, showing what you have typed",0dh,0ah,00h
name1 byte "enter some name: ",00h
error byte "oops, cannot insert this string, don't have free space in array",00h

        .CODE
main    PROC
;array with variable input string

        call    Clrscr ;clear the screen
        mov     edx, offset intro ;present the intro
        call    WriteString ;show intro on screen
include_next:
        mov     edx, offset name1 ;enter some name
        call    WriteString
mov ecx,80 ;max allowable number of chars, Irvine rules.
mov  edx,OFFSET stringIn ;the buffer that hold the string
mov  ecx,MAX            ;buffer size - 1
call ReadString ;return in eax the number of chars typed
mov esi, offset stringIn ;source
mov edi, offset MyArray ;destin

cmp eax,0 ;the user have typed a enter? Irvine rules here.
jne have_space ;no, so store what he have typed in array
jmp ended ;yes, so end

have_space:
add ARRAY_LENGHT,1 ;room for the counter
add ARRAY_LENGHT,eax ;in eax have the number of chars typed by the user
cmp ARRAY_LENGHT,ARRAY_SIZE ;the array is full?
jb include1 ;no, so find next room
mov edx, offset error ;yes, show error to user
call    WriteString
call WaitMsg
jmp ended ;and go to the end

include1:
add edi,PTR_ROOM ;moment1 is 0
mov byte ptr [edi],al ;we store first the counter of typed chars
inc PTR_ROOM ;and add 1 to ptr_room because counter have 1 byte
add PTR_ROOM,eax ;and add eax(al) because number or chars user have typed
inc edi ;next place
mov cl,al ;the counter goes to cl
again:
lodsb ;read 1 byte from our buffer
stosb ;and store in array
loop again ;and do this cl times
jmp include_next ;loop again
ended:
        call    Clrscr ;clear the screen
        mov     edx, offset intro1 ;show some intro to user
        call    WriteString
mov esi, offset MyArray ;esi == ptr to my array
cmp byte ptr [esi],0 ;is the first byte of array 0? so the user dont have inserted nothing in it, go out
je endend
again2:
lodsb ;load byte from buffer
cmp al,0 ;is zero? we get the end of array
je endend
mov cl,al ;that byte is a counter
continue_eco:
lodsb ;read cl times it and show a char in screen
call WriteChar
loop continue_eco
call Crlf
jmp again2
endend:
call WaitMsg
        exit
main    ENDP

        END     main

bcddd214

It get to the prompt and loops to the prompt again. I am trying to integrate a 'show_array' and see if the data is even making it in.

Here are a few questions:

stringIn BYTE MAX+1 DUP (?)  ;room for null
**Why room for null? What does null look like in this case?**

lodsb
***** How Does this work?******

I went over the code and can't figure out why she won't exit the loop or show the array data?

**********************code*************************

        TITLE   Random
        INCLUDE Irvine32.inc

        .DATA?
      
MAX = 80                     ;max chars allowed to read
stringIn BYTE MAX+1 DUP (?)  ;room for null
ARRAY_SIZE = 10000
MyArray byte ARRAY_SIZE dup(?) ;creates an empty array of ARRAY_SIZE bytes

        .DATA
Index       dd 0        ; define this Index
ARRAY_LENGHT DWORD 0
PTR_ROOM DWORD 0
intro byte "press enter in a blank line to exit this loop, while this",0dh,0ah,00h
intro1 byte "now, showing what you have typed",0dh,0ah,00h
name1 byte "enter some name: ",00h
error byte "oops, cannot insert this string, don't have free space in array",00h

        .CODE
main    PROC
;array with variable input string

        call    Clrscr ;clear the screen
        mov     edx, offset intro ;present the intro
        call    WriteString ;show intro on screen
include_next:
        mov     edx, offset name1 ;enter your name
        call    WriteString
      mov ecx,80
      mov  edx,OFFSET stringIn ;the buffer that hold the string
      mov  ecx,MAX            ;buffer size - 1
      call ReadString ;return in eax the number of chars typed
      mov esi, offset stringIn ;source
      mov edi, offset MyArray ;destin

      cmp eax,0 ;the user have typed a enter? Irvine rules here.
      jne have_space ;no, so store what he have typed in array
      call ShowArray
      call DumpRegs
      jmp ended ;yes, so end

have_space:
      add ARRAY_LENGHT,1 ;room for the counter
      add ARRAY_LENGHT,eax ;in eax have the number of chars typed by the user
      cmp ARRAY_LENGHT,ARRAY_SIZE ;the array is full?
      jb include1 ;no, so find next room
      mov edx, offset error ;yes, show error to user
      call    WriteString
      call WaitMsg
      jmp ended ;and go to the end

include1:
      add edi,PTR_ROOM ;moment1 is 0
      mov byte ptr [edi],al ;we store first the counter of typed chars
      inc PTR_ROOM ;and add 1 to ptr_room because counter have 1 byte
      add PTR_ROOM,eax ;and add eax(al) because number or chars user have typed
      inc edi ;next place
      mov cl,al ;the counter goes to cl
again:
      lodsb ;read 1 byte from our buffer
      stosb ;and store in array
      loop again ;and do this cl times
      jmp include_next ;loop again
ended:
        call    Clrscr ;clear the screen
        mov     edx, offset intro1 ;show some intro to user
        call    WriteString
      mov esi, offset MyArray ;esi == ptr to my array
      cmp byte ptr [esi],0 ;is the first byte of array 0? so the user dont have inserted nothing in it, go out
      je endend
again2:
       ;load byte from buffer
      cmp al,0 ;is zero? we get the end of array
      je endend
      mov cl,al ;that byte is a counter
continue_eco:
      lodsb ;read cl times it and show a char in screen
      call WriteChar
      loop continue_eco
      call Crlf
      jmp again2
endend:
call WaitMsg
        exit
main    ENDP

ShowArray       proc
                mov     edi, offset MyArray
                xor     ebx, ebx
    _next:      cmp     ebx, Index
                jne     @F
                ret
        @@:     mov     eax, [edi+ebx]    ; get EAX from the array
                add     ebx, 4            ; point to next dword
                call WriteInt
;            call Crlf
            jmp     _next
            ret
ShowArray       endp

        END     main

mineiro

Null is zero, in Irvine it mark the end of string.
From irvine book:
A null byte is stored following the characters input, but the trailing carriage return and line feed characters are not placed into the buffer.
   ECX should always be smaller that the buffer size (never equal to the buffer size) because the null byte could be the (ECX+1)th character stored.
So if your buffer have 2 bytes, you can only put one byte in it using Irvine, because it reserve some space to put a null(zero) byte at the end.

lodsb works like: read one byte from the pointer of esi and put this byte in al register, increase esi.
stosb works like: get the byte in al register and put it in the addres that edi point, increase edi.

a pseudo code for lodsb is:
mov esi, offset MyArray
mov al, byte ptr esi
inc esi

a pseudo code for stosb is:
mov edi, offset MyArray
mov byte ptr edi, al
inc edi

I don't understand why you are trying to put ShowArray procedure inside this one, if you explain, I can try to answer bcddd214.
regards.

bcddd214

Mainly to make sure I understand it.
I tried the code and even a null space would not jump the loop so I was doing some experimenting to see if I could just dump the contents of the array out and see what was going on..

mineiro

alright, I get the point, insert this in the previous example to show 256 bytes of MyArray in hexadecimal format.
You will see that it start only with zeros, and after each typed string, it get filled.

include_next:
;insert the lines below
      mov      esi, offset MyArray
      mov      ecx,256
      mov      ebx,1
      call    dumpmem
;ends here your insertion
        mov     edx, offset name1   ;enter some name

bcddd214

I still can't get it to escape out?
I try with a null space and without?

mineiro

change this:
intro   byte   "press enter in a blank line to exit this loop, while this",0dh,0ah,00h
to this:
intro   byte   "press \ in a blank line to exit this loop, while this",0dh,0ah,00h

and change this:
      mov      esi, offset stringIn   ;source
      mov      edi, offset MyArray      ;destin
      cmp      eax,0               ;the user have typed a enter? Irvine rules here.
      jne      have_space            ;no, so store what he have typed in array
      jmp      ended               ;yes, so end
have_space:


to this:
      mov      esi, offset stringIn   ;source
      mov      edi, offset MyArray      ;destin
      cmp      byte ptr stringIn,"\"
      je      ended
have_space:


now, if you press "\" in keyboard you exit the first loop.

bcddd214

 Assembling: 3-input-string-array.asm
3-input-string-array.asm(66) : error A2006: undefined symbol : intro1
3-input-string-array.asm(15) : error A2206: missing operator in expression
Press any key to continue . . .

***********************code**************************

        TITLE   Random
        INCLUDE Irvine32.inc

        .DATA?
      
MAX = 80                     ;max chars allowed to read
stringIn BYTE MAX+1 DUP (?)  ;room for null
ARRAY_SIZE = 10000
MyArray byte ARRAY_SIZE dup(?) ;creates an empty array of ARRAY_SIZE bytes

        .DATA
Index       dd 0        ; define this Index
ARRAY_LENGHT DWORD 0
PTR_ROOM DWORD 0
intro   byte   "press \ in a blank line to exit this loop, while this",0dh,0ah,00hintro1 byte "now, showing what you have typed",0dh,0ah,00h
name1 byte "enter some name: ",00h
error byte "oops, cannot insert this string, don't have free space in array",00h

        .CODE
main    PROC
;array with variable input string

        call    Clrscr ;clear the screen
        mov     edx, offset intro ;present the intro
        call    WriteString ;show intro on screen
include_next:
      mov      esi, offset MyArray
      mov      ecx,256
      mov      ebx,1
      call    dumpmem
        mov     edx, offset name1 ;enter your name
        call    WriteString
      mov ecx,80
      mov  edx,OFFSET stringIn ;the buffer that hold the string
      mov  ecx,MAX            ;buffer size - 1
      call ReadString ;return in eax the number of chars typed
      mov      esi, offset stringIn   ;source
      mov      edi, offset MyArray      ;destin
      cmp      byte ptr stringIn,"\"
      je      ended

have_space:
      add ARRAY_LENGHT,1 ;room for the counter
      add ARRAY_LENGHT,eax ;in eax have the number of chars typed by the user
      cmp ARRAY_LENGHT,ARRAY_SIZE ;the array is full?
      jb include1 ;no, so find next room
      mov edx, offset error ;yes, show error to user
      call    WriteString
      call WaitMsg
      jmp ended ;and go to the end

include1:
      add edi,PTR_ROOM ;moment1 is 0
      mov byte ptr [edi],al ;we store first the counter of typed chars
      inc PTR_ROOM ;and add 1 to ptr_room because counter have 1 byte
      add PTR_ROOM,eax ;and add eax(al) because number or chars user have typed
      inc edi ;next place
      mov cl,al ;the counter goes to cl
again:
      lodsb ;read 1 byte from our buffer
      stosb ;and store in array
      loop again ;and do this cl times
      jmp include_next ;loop again
ended:
        call    Clrscr ;clear the screen
        mov     edx, offset intro1 ;show some intro to user
        call    WriteString
      mov esi, offset MyArray ;esi == ptr to my array
      cmp byte ptr [esi],0 ;is the first byte of array 0? so the user dont have inserted nothing in it, go out
      je endend
again2:
       ;load byte from buffer
      cmp al,0 ;is zero? we get the end of array
      je endend
      mov cl,al ;that byte is a counter
continue_eco:
      lodsb ;read cl times it and show a char in screen
      call WriteChar
      loop continue_eco
      call Crlf
      jmp again2
endend:
call WaitMsg
        exit
main    ENDP

ShowArray       proc
                mov     edi, offset MyArray
                xor     ebx, ebx
    _next:      cmp     ebx, Index
                jne     @F
                ret
        @@:     mov     eax, [edi+ebx]    ; get EAX from the array
                add     ebx, 4            ; point to next dword
                call WriteInt
;            call Crlf
            jmp     _next
            ret
ShowArray       endp

        END     main

bcddd214

cut and paste error for the first error but intro is still undefined. I am guessing it does not want to read the procedure now?

jj2007

How do you want the assembler to interpret this??

intro   byte   "press \ in a blank line to exit this loop, while this",0dh,0ah,00hintro1 byte "now, showing what you have typed",0dh,0ah,00h

bcddd214

Quote from: jj2007 on April 28, 2011, 12:54:00 PM
How do you want the assembler to interpret this??

intro   byte   "press \ in a blank line to exit this loop, while this",0dh,0ah,00hintro1 byte "now, showing what you have typed",0dh,0ah,00h

sfu error
:)

RuiLoureiro

#29
bcddd214,
            Try this code and say what it does
            (i didnt test it, i havent Irvine32.inc)

            works corretly ? (type ENTER to exit)


TITLE   Strings
        INCLUDE Irvine32.inc

CpyStrArray proto   :DWORD,:DWORD,:DWORD,:DWORD
ShowString  proto   :DWORD,:DWORD

MAXLENGTH   equ 63
MAXLENGTH1  equ MAXLENGTH+1
MAXINDEX2    equ 100


.DATA
        Info1       db "Type your string",13,10, 0
       
        AnyString   db MAXLENGTH1 + 5 dup (?)   
        MyStrArray  db MAXLENGTH1 * MAXINDEX2 dup (?)
        MaxIndex    dd 0

        CRLF1        db 13, 10, 0
.CODE
main        proc

    _next:  call    Clrscr ;clear the screen

            mov     edx, offset Info1
            call    WriteString
            ;
            ; Read the string to AnyString
            ; ----------------------------
      mov     edx, offset AnyString ;the buffer that hold the string
      mov     ecx, MAXLENGTH      ;buffer size - 1
      call    ReadString       ;return in eax the number of chars typed
            ;
            cmp     eax, 0                ; EAX=length
            je      _exit
            ;
            ; Put AnyString into MyStrArray
            ; -----------------------------
            add     MaxIndex, 1
            invoke  CpyStrArray, offset AnyString, eax, offset MyStrArray, MaxIndex

            jmp     _next
;-------------*****------------------
;  Show each string one after another
;-------------*****------------------
    _exit:  call    Clrscr ;clear the screen

            invoke  ShowString, addr MyStrArray, MaxIndex

            call    WaitMsg
            exit
main        endp
;----------------------------
CpyStrArray proc    pSrc:DWORD, lSrc:DWORD, pDst:DWORD, Idx:DWORD
            push    esi
            push    edi

            mov     ecx, Idx
            cmp     ecx, 0
            je      _exit
            ;
            cmp     ecx, MAXINDEX2
            ja      _exit

            mov      edi, pDst           ; point to array
            ;
            mov      eax, MAXLENGTH1
            sub      ecx, 1
            mul      ecx
            add      edi, eax                ; EDI points to MyStrArray[N]
            ;
            mov     esi, pSrc           ; source
            mov     ecx, lSrc           ; length=number of chars
           
            mov     byte ptr [edi + ecx], 0  ; null terminated string           
            ;
            ; copy from last to first
            ; »»»»»»»»»»»»»»»»»»»»»»»
    @@:     sub     ecx, 1
            movzx   eax, byte ptr [esi + ecx]
            mov     byte ptr [edi + ecx], al
            jnz     short @B           
           
    _exit:  pop     edi
            pop     esi
            ret
CpyStrArray endp
;------------------------------
ShowString  proc    pArray:DWORD, IdxMax:DWORD
            push    ebx
            push    esi
            ;
            xor     ebx, ebx                ; index
           
            mov     esi, pArray
            mov     ecx, IdxMax
            ;
            cmp     ecx, 0
            je      _end
            ;
    @@:     mov     eax, MAXLENGTH1
            mul     ebx
            ;
            mov     edx, eax
            add     edx, esi
call    WriteString

            mov     edx, offset CRLF1
            call    WriteString
            ;
            add     ebx, 1                  ; next index
            sub     ecx, 1
            jnz     short @B
           
    _end:   pop     esi
            pop     ebx
            ret
ShowString  endp
        END     main