CS2400 ARM assembly programming classwork problems.
Follow the instructions for each of the following code samples in Compliler Explorer.
-
- What is the library function that is called?
- Research the implementation (source code) of this function.
- Find out if the program directly executes the output operation or it makes a system call to the operating system.
-
- How are the arguments passed to
malloc
andfree
? - Research the implementation (source code) of
malloc
andfree
.
- How are the arguments passed to
-
- How does this case differ from the previous one?
- [hard] Write your own tiny
malloc
library by declaring a largeFILL
area and writing amalloc
and afree
subroutines that manage allocations to that memory area.malloc
works approximately as follows:- it takes as argument the number of bytes requested
- it finds an appropriate region of the heap that can satisfy the request and marks it as allocated
- it adds a small metadata memory block of known size on top of the region and writes the size of the region in the block
- returns a pointer to the region, not including the metadata block
- if the allocation fails for any reason (e.g. running out of memory), it returns
NULL
(0x00000000), which is an invalid address for user programs - allocates regions in from-lower-to-higher address orientation
free
works approximately as follows:- it takes the pointer returned by
malloc
- it subtracts the size of the metadata block from this address
- it reads the size of the allocated region
- it marks the cumulative (metadata block + region) previously allocated area as available
- it takes the pointer returned by
- Non-interleaving of calls:
- assume all the calls to
malloc
precede all the calls tofree
- assume the
free
calls will be made in the reverse order of themalloc
calls, as inint *p1 = (int *) malloc(200 * sizeof(int)); int *p2 = (int *) malloc(300 * sizeof(int)); int *p3 = (int *) malloc(100 * sizeof(int)); // use memory... free(p3); free(p2); free(p1);
- this relieves you from the responsibility to manage holes in the memory area
- assume all the calls to
- Variables you will need:
memstore
(standing for memory store) - starting address of the fill areastoreptr
(standing for store pointer) - a pointer to the next available memory region
- Stack:
- manage the subroutine (aka function) calls by creating stack frames for them to hold their arguments as well as any local variables that are needed
- don't forget to manage the register bank and not overwrite register value that are needed by the caller
- if you need to save registers on the stack, you can do it within the frame of the callee, correctly expanding the frame to fit them (note that VisUAL does not support
push
andpop
) - note that a function's stack frame only lasts between the start and end of execution of the subroutine, regardless of how many times the subroutine is called
- When
malloc
returnsNULL
:- when you have less memory than the next requested size
- when the request is not a multiple of 4 (due to the VisUAL limitation of addressing only words and correspondingly the
FILL
regions only take multiples of 4)
-
- Port this code to VisUAL.
- for an example, refer to the negate repo
- Open the Compiler Explorer
- Select the ARM gcc 8.2 compiler
- Enter the following compiler options in the box on the right:
-fomit-frame-pointer -mcpu=cortex-m3 -mtune=cortex-m3
- Put the code of the
negate.c
file in the left pane - The compiler will generate the assembly for the long
negate
program, that is not directly executable in VisUAL - The file
negate_gcc_8_2.S
contains the assembly ported to VisUAL
- special attention on:
- Unsupported instructions (Just Execute on VisUAL and it will mark them)
- in particular,
BX
is not supported, so you will need to use a new label orMOV pc, rl
to return from a subroutine
- in particular,
- Memory regions (VisUAL only supports
DCD
andFILL
directives) - Start of execution (VisUAL starts executing the top line, so you might need to rearrange your code)
- alternatively, you can define a
_start
label and load it intopc
- alternatively, you can define a
- Unsupported instructions (Just Execute on VisUAL and it will mark them)
- for an example, refer to the negate repo
- Observe/show that this code writes the local array in reverse order to the
static
global array.
- Port this code to VisUAL.
-
- Port this code to VisUAL.
- How are nested
for
loops handled in assembly? Are they "nested" in assembly?
-
- Port this code to VisUAL. (It's the same as the previous but with multiplicatoin).
- Add your 32-bit unsigned integer multiplication algorithm as a subroutine and run the code. Verify its correctness.
- Fork this repository
- Clone and implement.
- Commit any modifications.
- Push your commits to your remote.
- For research-type questions, answer inline in the README.
- Important: Submit the URL of your remote repository on Google Classroom, as a private comment.