Using Our Allocator


The programs we do in this book aren't complicated enough to necessitate a memory manager. Therefore, we will just use our memory manager to allocate a buffer for one of our file reading/writing programs instead of assigning it in the .bss.

The program we will demonstrate this on is read-records.s from Chapter 6. This program uses a buffer named record_buffer to handle its input/output needs. We will simply change this from being a buffer defined in .bss to being a pointer to a dynamically-allocated buffer using our memory manager. You will need to have the code from that program handy as we will only be discussing the changes in this section.

The first change we need to make is in the declaration. Currently it looks like this:

  .section .bss  .lcomm, record_buffer, RECORD_SIZE 

It would be a misnomer to keep the same name, since we are switching it from being an actual buffer to being a pointer to a buffer. In addition, it now only needs to be one word big (enough to hold a pointer). The new declaration will stay in the .data section and look like this:

 record_buffer_ptr:  .long 0 

Our next change is we need to initialize our memory manager immediately after we start our program. Therefore, right after the stack is set up, the following call needs to be added:

  call allocate_init 

After that, the memory manager is ready to start servicing memory allocation requests. We need to allocate enough memory to hold these records that we are reading. Therefore, we will call allocate to allocate this memory, and then save the pointer it returns into record_buffer_ptr. Like this:

  pushl $RECORD_SIZE  call  allocate  movl  %eax, record_buffer_ptr 

Now, when we make the call to read_record, it is expecting a pointer. In the old code, the pointer was the immediate-mode reference to record_buffer. Now, record_buffer_ptr just holds the pointer rather than the buffer itself. Therefore, we must do a direct mode load to get the value in record_buffer_ptr. We need to remove this line:

 pushl $record_buffer 

And put this line in its place:

 pushl record_buffer_ptr 

The next change comes when we are trying to find the address of the firstname field of our record. In the old code, it was $RECORD_FIRSTNAME + record_buffer. However, that only works because it is a constant offset from a constant address. In the new code, it is the offset of an address stored in record_buffer_ptr. To get that value, we will need to move the pointer into a register, and then add $RECORD_FIRSTNAME to it to get the pointer. So where we have the following code:

  pushl $RECORD_FIRSTNAME + record_buffer 

We need to replace it with this:

  movl  record_buffer_ptr, %eax  addl  $RECORD_FIRSTNAME, %eax  pushl %eax 

Similarly, we need to change the line that says

  movl  $RECORD_FIRSTNAME + record_buffer, %ecx 

so that it reads like this:

  movl  record_buffer_ptr, %ecx  addl  $RECORD_FIRSTNAME, %ecx 

Finally, one change that we need to make is to deallocate the memory once we are done with it (in this program it's not necessary, but it's a good practice anyway). To do that, we just send record_buffer_ptr to the deallocate function right before exitting:

  pushl record_buffer_ptr  call  deallocate 

Now you can build your program with the following commands:

 as read-records.s -o read-records.o ld alloc.o read-record.o read-records.o write-newline.o count- chars.o -o read-records 

You can then run your program by doing ./read-records.

The uses of dynamic memory allocation may not be apparent to you at this point, but as you go from academic exercises to real-life programs you will use it continually.




Programming from the Ground Up
Programming from the Ground Up
ISBN: 0975283847
EAN: 2147483647
Year: 2006
Pages: 137

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net