Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # Mips Memory Manager - A Small program in mips to handle allocating and dealocating memory
- # Copyright (C) 2012 Erick "RetroZelda" Folckemer
- # This program is free software: you can redistribute it and/or modify
- # it under the terms of the GNU General Public License as published by
- # the Free Software Foundation, either version 3 of the License, or
- # at your option) any later version.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
- .data
- ##### Block header Layout #####
- # 0) 4 bytes - size of block
- # 4) 4 bytes - address of prev block header; 0 if none
- # 8) 1 byte - 0 if free, non-zero if not free
- # 9) 3 bytes - padding for word alignment
- # 12) open data start offset
- # header size - 12 bytes
- #
- #
- Memory_Size_Total: .word 0x8000 # 32kb
- Memory_Header_Size: .word 12 # 12 bytes
- Memory: .word 0x10040000 # heap starting address
- print_block_size: .asciiz "block size: "
- print_block_prev: .asciiz "\nblock prev: "
- print_block_addr: .asciiz "\nblock address: "
- print_new_line: .asciiz "\n"
- print_no_memory: .asciiz "***** Out of Memory *****\n"
- print_leaked_memory: .asciiz " Warning: Memory has been leaked!\n"
- .text
- main:
- jal init # init the memory blocks
- lw $a0, Memory # move our Memory address to display
- addi $a0, $a0, 12 # move to start of data block
- jal debug_print_block # display memory stats
- li $s1, 0 # start loop count
- allocate_loop:
- li $a0, 2048 # 2kb of data requested
- jal malloc # allocate the 2kb
- beqz $v0, no_memory_leave_loop # if malloc fails then leave this loop
- subi $sp, $sp, 4 # get room on stack
- sw $v0, 0($sp) # save address of allocated block onto stack
- move $a0, $v0 # move our allocated memory to a0 to print
- jal debug_print_block # print the info of this memory block
- addi $s1, $s1, 1 #increase loop count
- j allocate_loop
- no_memory_leave_loop:
- li $v0, 4 # print string syscall
- la $a0, print_no_memory
- syscall
- deallocate_loop:
- lw $a0, 0($sp) # get last address off stack
- addi $sp, $sp, 4 # move stack up
- jal free # free the memory
- subi $s1, $s1, 1 # decrease counter
- bnez $s1, deallocate_loop # keep going until counter is 0
- lw $t0, Memory_Size_Total # load total size
- lw $t1, Memory_Header_Size # load header size
- sub $t0, $t0, $t1 # remove header size from total size
- lw $t1, Memory # load start address
- lw $t1, 0($t1) # load remaining memory size
- beq $t1, $t0, exit_main # if remaining size != total size(minus the header) then we have a leak/problem
- li $v0, 4 # print string
- la $a0, print_leaked_memory
- syscall
- exit_main:
- lw $a0, Memory # move our Memory address to display
- addi $a0, $a0, 12 # move to start of data block
- jal debug_print_block # display memory stats
- li $v0, 10
- syscall
- ########## sub routines ############
- ####################################
- ##########################################
- ### init - initializes the memory pool ###
- init:
- li $t0, 0
- lw $t1, Memory # load the address of our memory
- lw $t2, Memory_Size_Total # load in the address of the total size
- lw $t3, Memory_Header_Size # load the header size
- sb $t0, 8($t1) # mark memory as free
- sw $t0, 4($t1) # there isnt a prev block
- sub $t2, $t2, $t3 # update the space of the entire block remaining
- sw $t2, 0($t1) # set the bytes remaining for the block
- jr $ra
- ################ init end ################
- ##########################################
- ###############################
- ### malloc - allocates data ###
- # in:
- ## a0 length of allocation
- # out:
- ## v0 - address of memory region
- ### - 0 if unavailable
- malloc:
- lw $t0, Memory # load the address of our memory
- lw $t1, Memory_Size_Total # load in the address of the total size
- lw $t3, Memory_Header_Size # load the header size
- lw $t4, Memory # the starting header to start
- add $t5, $t0, $t1 # the address of the end of the memory pool
- find_open_block:
- lb $t7, 8($t4) # load the free-byte
- bnez $t7, goto_next_block # keep looping if block isnt free
- lb $t7, 0($t4) # load the block size
- bge $a0, $t7, claim_open_block # stop looping; we can safely claim the block if enough space is available
- goto_next_block:
- addi $t6, $t4, 0 # save the prev block
- lw $t7, 0($t4) # save the block size
- add $t4, $t4, $t7 # increase by the block size
- add $t4, $t4, $t3 # increase by the header size(positived)
- bge $t4, $t5, no_open_blocks # we have passed the edge of the available pool
- j find_open_block # keep the block check going
- claim_open_block:
- lw $t8, 0($t4) # cache the block size
- bgt $a0, $t8, no_open_blocks # we will pass edge of available pool
- sw $a0, 0($t4) # save the block size
- sw $t6, 4($t4) # save the prev addr in header
- la $t6, 0xffffffff # create a non-zero word to get a byte from
- sb $t6, 8($t4) # make free-byte be taken
- add $v0, $t4, $t3 # get the address of data-safe memory to return
- add $t6, $v0, $a0 # get address after our memory block
- sub $t8, $t8, $a0 # get the size of remaining space in old block
- sub $t8, $t8, $t3 # dont forget to remove header size from remaining size
- beqz $t8 return_from_malloc # if the block claim was snug, we can just leave
- sw $t8, 0($t6) # save new block size
- sw $v0, 4($t6) # save the new block as the prev block
- sb $zero, 8($t6) # this block is free
- j return_from_malloc # we can leave :)
- no_open_blocks:
- li $v0, 0 # load 0 to mark the function failed
- return_from_malloc:
- jr $ra # return from malloc
- ########## malloc end ##########
- ################################
- ##################################
- ### free - free allocated data ###
- # in:
- ## a0 address of allocated block
- ## NOTE: Should clean up registers being used and where/how they are used to make clearer/cleaner
- free:
- sb $zero, -4($a0) # mark memory as free
- lw $t0, -8($a0) # load the prev block
- lw $t2, Memory_Header_Size # load the header size
- merge_right:
- lw $t1, -12($a0) # load the block size
- add $t1, $t1, $a0 # get the address to the next block
- lw $t3, Memory # load memory start address
- lw $t4, Memory_Size_Total # load total memory size
- add $t3, $t3, $t4 # get the address of the end of available memory
- bge $t1, $t3, merge_left # leave if next block is out of bounds
- lw $t3, 8($t1) # load the free byte in the next block
- bnez $t3, merge_left # leave if next block isnt free
- lw $t3, 0($t1) # load in the next block size
- lw $t4, -12($a0) # load in current block size
- add $t3, $t3, $t4 # combine the sizes
- add $t3, $t3, $t2 # include the header size
- sw $t3, -12($a0) # save the combined size
- merge_left:
- beqz $t0, return_from_free # if zero then we cant merge left
- lb $t1, 8($t0) # load the free byte
- bnez $t1, return_from_free # if not free, we cant merge left
- lw $t1, 0($t0) # load in the prev block size
- lw $t4, -12($a0) # load in current block size
- add $t1, $t1, $t4 # combine the sizes
- add $t1, $t1, $t2 # include the header size
- sw $t1, -12($a0) # save the combines size
- return_from_free:
- jr $ra # return from malloc
- ########### free end ###########
- ################################
- ###################################################
- ### debug_print_block - prints block to console ###
- # in:
- ## a0 - address of memory block
- debug_print_block:
- move $t0, $a0 # save the address
- li $v0, 4 # print string syscall
- la $a0, print_block_size
- syscall
- li $v0, 1 # print int syscall
- lw $a0, -12($t0) # value is block size
- syscall
- li $v0, 4 # print string syscall
- la $a0, print_block_prev
- syscall
- li $v0, 1 # print int syscall
- lw $a0, -8($t0) # value is block prev
- syscall
- li $v0, 4 # print string syscall
- la $a0, print_block_addr
- syscall
- li $v0, 1 # print int syscall
- la $a0, ($t0) # value is block prev
- syscall
- li $v0, 4 # print string syscall
- la $a0, print_new_line
- syscall
- jr $ra # return from debug_print_block
- ############## debug_print_block end ##############
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement