Programming - Assembly Heap Memory Allocation

    Hello! It's me again. Today we will talk about Dynamic Memory Allocation using the Program Heap. To do it we will use memory instructions and a system call we already shown, but never used. So, without further do, let's get started!


Heap:

    To allocate memory dynamically when running our code and not as variables we will use the program heap. We don't actually need to know exactly how it works, but to just make it clear: It's an area of our running Code (Thread or Process) save location that let's us allocate memory on the fly. It's not infinite, but it's more than enough for the most parts! So, we will use instructions to allocate memory of specific byte size and afterwards store into that newly allocated memory location anything that we wish.


Allocate memory:

    To allocate this memory we use system call 9. This system call gets an byte value as input, allocates the memory for us on an address and returns the address of that block.

The code looks like this:

li $v0, 9 # memory allocation code
li $a0, SIZE # byte size
syscall
# $v0 then contains the address of the block allocated


    When allocating integer memory we should always allocate 4 bytes for each integers and when having char's 1 byte for each is enough. You can get the size value as input to make it more dynamic (example code).

Store into/ Load from allocated memory:

    To store into that memory we will use the sw instruction in the same way we did previously. The problem is when you want to do stuff inside of a loop and not directly and when having the address stored into an register, you can't just use 2 registers as parameters. That's why we first add those to values into one using addu and afterwards call the sw function with one register value inside of ( ).

So, when wanting to store into an address we can use:

  • One simple sw $r1, 0($r2), sw $r1, 4($r2), ... when having only one register parameter
  • addu $r1, $r2, $r3 and sw $r4, ($r1) when having two register parameters, two make it into one address before storing

    To load from this location the code looks exactly the same and we again use the lw instruction in any of the two ways I told you today.

Example Code:

    An simple program that gets a size value as input, allocates a dynamic integer array of that size, gets integer values and stores them into this array and afterwards prints the array looks like this:

.data
# define input strings
size: .asciiz "Give array size: "
input : .asciiz "Give a number: "
space: .asciiz " "
newline: .asciiz "\n"

.text
main:
# print message for getting size
li $v0, 4
la $a0, size
syscall

# get size input
li $v0, 5
syscall
move $s0, $v0

# change to bytes
mul $s0, $s0, 4
# s0 now contains the bytes

# allocate dynamic memory
li $v0, 9
move $a0, $s0
syscall
move $s1, $v0
# s1 now contains the address

# loop to get input
li $t0, 0 # loop counter
for:

# check loop condition
bge $t0, $s0, end_for

# print message for getting input
li $v0, 4
la $a0, input
syscall

# get integer input
li $v0, 5
syscall
move $t1, $v0

# write into array/address
addu $t2, $s1, $t0
sw $t1, ($t2)

# increment loop counter
addi $t0, $t0, 4

j for
end_for:

# print array

li $t0, 0 # loop counter
for2:

# check loop condition
bge $t0, $s0, end_for2

# load from array/address
addu $t2, $s1, $t0
lw $t1, ($t2)

# print integer
li $v0, 1
move $a0, $t1
syscall

# print space
li $v0, 4
la $a0, space
syscall

# increment loop counter
addi $t0, $t0, 4

j for2
end_for2:

# print newline
li $v0, 4
la $a0, newline
syscall

# terminate programm
li $v0, 10
syscall


This was the end of today's post. Hope you enjoyed it!

    Next time we will talk about Files in Assembly (last basic post, cause then I will only post more advanced stuff from time to time) and then I will start with Logic Design, to give you enough theory knowledge about Logic Circuits so that I can get into VHDL Coding :)

Until next time...

H2
H3
H4
3 columns
2 columns
1 column
Join the conversation now