Author Topic: How to create dynamic array ?  (Read 10353 times)

Offline dearhuseyin

  • Jr. Member
  • *
  • Posts: 3
How to create dynamic array ?
« on: July 06, 2013, 05:35:04 PM »
Hello I try to create an dynamic array but i couldn't.
Please Give an example for it
Thanks for helps

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2382
  • Country: us
Re: How to create dynamic array ?
« Reply #1 on: July 06, 2013, 09:59:31 PM »
What have you tried? Where did it go wrong? What part(s) do you need help with?

Seems to me "dynamic array" would imply memory allocation, which would be an OS function. What OS? I suppose could use C library functions... try to make it "portable". If for 64-bit, they've even screwed that up! I'd want a pretty good "specification" before I could even think about an example. What's this program need to do, exactly?

When I don't know what to do, "write the comments first" sometimes works. :)

Best,
Frank


Offline dearhuseyin

  • Jr. Member
  • *
  • Posts: 3
Re: How to create dynamic array ?
« Reply #2 on: July 06, 2013, 10:44:08 PM »
Hello Frank
Thanks for reply

I say "dynamic array",I mean to like auto increment size array. I am sorry my English isn't very good :(  For Example;

int somevar[];

how to create this ?
I use Win32.

Quote
When I don't know what to do, "write the comments first" sometimes works. :)
Certainly :)

Best,
Huseyin

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2382
  • Country: us
Re: How to create dynamic array ?
« Reply #3 on: July 10, 2013, 12:51:51 AM »
Hi Huseyin,

Well...

Code: [Select]
ITEM_SIZE equ 4 ; ints or single precision floats?
ARRAY_SIZE equ 100 ;number of items in array

section .bss
array resb ITEM_SIZE * ARRAY_SIZE


But that's not dynamic. I think we're going to have to...
Code: [Select]
section .bss
arrayptr resd 1
... and "malloc()" as we go along. Actually, I don't  think repeated calls to "malloc()" will give us contiguous memory, which would be a pain. I think we're going to want to malloc() one block, and enlarge it as we go along with realloc(). Or can we use realloc() right from the start? As you can tell, I don't really know how to do this. I think I'm going to have to go read those man pages again. I'll try to get back to this...

Best,
Frank


Offline Gunner

  • Jr. Member
  • *
  • Posts: 74
  • Country: us
    • Gunners Software
Re: How to create dynamic array ?
« Reply #4 on: July 10, 2013, 01:31:17 AM »
For Windows, you could use the Heap* functions from Kernel32.dll - Memory Management Functions

Call GetProcessHeap at beginning of program to get a handle to your exes' heap, then to create the "array" use HeapAlloc which returns a pointer to the newly allocated memory.  To dynamically resize this "array" call HeapReAlloc.

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2382
  • Country: us
Re: How to create dynamic array ?
« Reply #5 on: July 10, 2013, 10:20:32 PM »
Yeah, the Windows APIs are probably better for this. I was thinking of C library functions to try to make it portable, but that's probably futile.

I thought I might soon have a Windows machine to play with. My daughter gave me her old computer which had Windows on it. I thought of keeping it on there as an alternate boot... but made the mistake of reading the terms and conditions I was agreeing to. Naw, I guess not. Maybe think about looking at Wine again...

Best,
Frank


Offline dearhuseyin

  • Jr. Member
  • *
  • Posts: 3
Re: How to create dynamic array ?
« Reply #6 on: July 11, 2013, 03:10:12 PM »
Thanks for replies :) I understand this

Offline Bryant Keller

  • Forum Moderator
  • Full Member
  • *****
  • Posts: 360
  • Country: us
    • About Bryant Keller
Re: How to create dynamic array ?
« Reply #7 on: July 16, 2013, 02:51:57 AM »
As Frank mentioned, a "portable" solution would be to use the C library functions to handle this. The ones you should be interested in are malloc(), realloc(), and free(). Malloc will allocate a block of data on the stack, realloc will attempt to resize that block of memory, and free will make that block of memory available for other parts of the program.

This is a very quick example, it's not optimized and I tried to document it well enough for you to get a good idea of what's going on. I execute 3 for loops, I could have used 2 (as the second is a copy of the first) but that would have required keeping track of the number of times the loop itself had been executed, and I thought it might unnecessarily obfuscate the source code.

Code: (demo.asm) [Select]
;; Filename: demo.asm
;; Developer: Bryant Keller
;; Purpose: To show dearhuseyin how a dynamic array in NASM might work.
;; Build:
;; Assemble: nasm -f elf demo.asm -o demo.o
;; Link: gcc demo.o -o demo
;; Execute: ./demo

bits 32
cpu 486

extern printf
extern malloc
extern realloc
extern free

;; In this example, we will create a dynamic array. Because it's
;; dynamic, we need a method to keep track of the number of elements
;; in the array. This way, we can tell if we need to resize the array.
struc DARRAY
.ptr: resd 1 ; Pointer to our block of memory. (contents of the array)
.count: resd 1 ; Number of elements currently allocated.
endstruc

section .rodata

;; This is a linux system, so I put my format strings in the
;; read-only data section. GCC/LD likes this.

fmt: DB "[%d] = %d", 10, 0

section .bss

;; We will place our dynamic array variable and a global index
;; into the unintialized data section. That way it doesn't actually
;; add to the size of our executable, it'll be created at runtime.

myArray: resb DARRAY_size
index: resd 1

section .text

;; We start our program with the main procedure. Since we will be using
;; printf, we want to make sure that C produces it's startup code.

global main

main: push ebp
mov ebp, esp

;; Our dynamic array will contain 10 elements.
mov eax, 10
mov dword [myArray + DARRAY.count], eax

;; Each element will be treated as an integer. (eg. count * sizeof(int))
sal eax, 2

;; We allocate our elements on the heap.
push eax
call malloc
add esp, 4

;; And we save a pointer to the first element in our array.
mov dword [myArray + DARRAY.ptr], eax

;; We initialize our array's index to zero.
mov dword [index], 0

;; And immediately jump to our comparison.
jmp for_loop_1.compare

for_loop_1:

;; This is our "For Loop" body.

;; First we obtain the pointer to our array...
mov eax, dword [myArray + DARRAY.ptr]

;; .. and the current value of our index.
mov edx, dword [index]

;; We now get the address of the nth element of our array. (eg. array[index])
sal edx, 2 ; index * sizeof(int)
lea edx, [eax + edx]

;; And we store the current index in it.
mov eax, dword [index]
mov dword [edx], eax

;; And finally we increment our index.
inc dword [index]

.compare:
;; If the index is less than the array's size, we continue.
mov edx, dword [index]
mov eax, dword [myArray + DARRAY.count]
cmp edx, eax
jb for_loop_1

;; Once we've looped through all 10 elements, we've decide to add 3 more.

;; Add 3 to our count...
mov eax, dword [myArray + DARRAY.count]
add eax, 3
mov dword [myArray + DARRAY.count], eax

;;... then update adjust the count to byte size. (eg. count * sizeof(int))
sal eax, 2

;; We reallocate our heap for the 3 extra elements.
push eax
push dword [myArray + DARRAY.ptr]
call realloc
add esp, 8

;; And update our pointer.
mov dword [myArray + DARRAY.ptr], eax

;; Now we continue updating values.
jmp for_loop_2.compare

;; This for loop is just like the last one, except that
;; we don't zero initialize our index. In this loop, we
;; will start from where we left off.

for_loop_2:
mov eax, dword [myArray + DARRAY.ptr]
mov edx, dword [index]
sal edx, 2
lea edx, [eax + edx]
mov eax, dword [index]
mov dword [edx], eax
inc dword [index]

.compare:
mov edx, dword [index]
mov eax, dword [myArray + DARRAY.count]
cmp edx, eax
jb for_loop_2

;; Once we have updated all the elements, we need
;; to start back over at the beginning, so we zero
;; initialize index, and jump to our comparison.

mov dword [index], 0
jmp for_loop_3.compare

for_loop_3:
;; This time, we grab the integer of the element at the current index.
;; (eg. eax = array[index])
mov eax, dword [myArray + DARRAY.ptr]
mov edx, dword [index]
sal edx, 2 ; edx = index * sizeof(int)
add eax, edx ; eax = array[index]

;; Now we will display the results to the screen.
push dword [eax] ; array[index]
push dword [index] ; index
push dword fmt ; "[%d] = %d\n"
call printf
add esp, 12

;; And we move on to the next element.
inc dword [index]

.compare:
;; Once again, if the index is less than the count
;; we will continue.
mov edx, dword [index]
mov eax, dword [myArray + DARRAY.count]
cmp edx, eax
jb for_loop_3

;; Once we have displayed the contents of the array, we no longer
;; actually need it. Let's be good and free the memory.

push dword [myArray + DARRAY.ptr]
call free
add esp, 4

;; And finally we return an exit code of 0 (stdlib.h, EXIT_SUCCESS)
mov eax, 0
leave
ret

The expected output is:

Code: (xterm) [Select]
$ ./demo
[0] = 0
[1] = 1
[2] = 2
[3] = 3
[4] = 4
[5] = 5
[6] = 6
[7] = 7
[8] = 8
[9] = 9
[10] = 10
[11] = 11
[12] = 12
$

HtH,
~ Bryant
« Last Edit: July 16, 2013, 02:55:11 AM by Bryant Keller »

About Bryant Keller
bkeller@about.me