user1769457
user1769457

Reputation: 11

Printing an array of strings in assembly language

I am trying to add strings to an array for later printing from the array and this is what I have. What am I missing?

INCLUDE Irvine32.inc
.data
array dword 20 dup (0)
str1 byte 20 dup (0)
temp dword ?
n dword ?
count dword 0

mes1 db "press 1 to add an element, 2 to print, 3 to quit    ", 0

.code
main PROC

start:
    lea edx, mes1
    call writestring
    call readdec
    cmp eax, 1
    je add1
    cmp eax, 2
    je print2
    cmp eax, 3
    je stop

add1:
    call readin
    jmp done

print2:
    call print
    jmp done

done:
    jmp start

stop:
    exit

main ENDP

readin proc
    lea edx, str1
    mov ecx, sizeof str1
    call readstring

    mov ebx, count
    mov eax, [array]
    mov temp, eax
    add temp, ebx
    lea esi, temp
    mov ebx, [str1]
    mov [esi], ebx

readin endp

print proc
    mov esi, 0
    mov ecx, n

    @@do:
        mov eax, Array[esi]
        call writedec
        call crlf
        add esi, 4
        @@while: loop @@do

        ret
print endp
END main

Upvotes: 1

Views: 9121

Answers (1)

rkhb
rkhb

Reputation: 14409

The simplest solution is to create an array of bytes that contains null-terminated strings in a row. This is not really an "array of strings". Ingredients: A big buffer and a pointer that points to the end of the valid part of that buffer.

INCLUDE Irvine32.inc

.DATA

    arrayptr    DWORD OFFSET array
    array       BYTE 4096 DUP (?)

    mes1        BYTE 10, "press 1 to add an element, 2 to print, 3 to quit    ", 0

.CODE

readin PROC
    mov edx, arrayptr           ; Argument for ReadString: Pointer to memory
    mov ecx, 10                 ; Argument for ReadString: maximal number of chars
    call ReadString             ; Doesn't change EDX
    test eax, eax               ; EAX == 0 (got no string)
    jz done                     ; Yes: don't store a new arrayptr
    lea edx, [edx+eax+1]        ; EDX += EAX + 1
    mov arrayptr, edx           ; New pointer, points to the byte where the next string should begin
    done:
    ret
readin ENDP

print PROC
    lea edx, array              ; Points to the first string

    L1:
    cmp edx, arrayptr           ; Does it point beyond the strings?
    jae done                    ; Yes -> break

    call WriteString            ; Doesn't change EDX
    call Crlf                   ; Doesn't change EDX

    scan_for_null:
    inc edx
    cmp BYTE PTR [edx], 0       ; Terminating null?
    jne scan_for_null           ; no -> next character
    inc edx                     ; Pointer to next string

    jmp L1

    done:
    ret
print ENDP

main PROC
start:
    lea edx, mes1
    call WriteString
    call ReadDec
    cmp eax, 1
    je add1
    cmp eax, 2
    je print2
    cmp eax, 3
    je stop
    jmp next                    ; This was missing in the OP

add1:
    call readin
    jmp next                    ; Just a better name than in the OP

print2:
    call print
    jmp next                    ; Just a better name than in the OP

next:                           ; Just a better name than in the OP
    jmp start

stop:
    exit
main ENDP

END main

The elements of an array all have typically the same size (bytes in the example above). So the position of an element can be indexed and easily calculated with that index. It's not as easy to determine the position of a certain string inside of an array of bytes. The array must be scanned from the beginning for string-terminating zeros (take a look at the block scan_for_null). An "array of strings" is actually an array of pointers to strings:

INCLUDE Irvine32.inc

.DATA

    bufptr      DWORD OFFSET buf    ; Pointer to the beginning of free buffer
    buf         BYTE 4096 DUP (?)   ; Space for 4096 characters
    array       DWORD 20 DUP (?)    ; Space for 20 pointers
    arrayindex  DWORD 0             ; Index of the next free pointer in array

    mes1        BYTE 10, "press 1 to add an element, 2 to print, 3 to quit    ", 0

.CODE

readin PROC
    mov edx, bufptr             ; Argument for ReadString: Pointer to memory
    mov ecx, 10                 ; Argument for ReadString: maximal number of chars
    call ReadString             ; Doesn't change EDX
    test eax, eax               ; EAX == 0 (got no string)
    jz done                     ; Yes: don't change bufptr
    mov esi, arrayindex
    mov [array + esi * 4], edx  ; Store the actual bufptr
    inc arrayindex
    lea edx, [edx+eax+1]        ; EDX += EAX + 1 (new bufptr)
    mov bufptr, edx             ; New pointer, points to the byte where the next string should begin
    done:
    ret
readin ENDP

print PROC
    xor esi, esi                ; First index

    L1:
    cmp esi, arrayindex         ; Beyond last index?
    jae done                    ; Yes -> break

    mov edx, [array + esi * 4]  ; Argument for WriteString: pointer to a null-terminated string
    call WriteString
    call Crlf

    inc esi
    jmp L1

    done:
    ret
print ENDP

main PROC
start:
    lea edx, mes1
    call WriteString
    call ReadDec
    cmp eax, 1
    je add1
    cmp eax, 2
    je print2
    cmp eax, 3
    je stop
    jmp next

add1:
    call readin
    jmp next

print2:
    call print
    jmp next

next:
    jmp start

stop:
    exit
main ENDP

END main

Upvotes: 1

Related Questions