Reputation: 325
I have this C code :
void initPIO_Port(AT91S_PIO *port)
{
port->PIO_PER=1<<PIN;
port->PIO_OER=1<<PIN;
} // initPIO_Port
int main(void)
{
initPIO_Port(PORT);
/* Loop for ever */
while (1) {
...
};
}
translated to ARM assembly by arm-gcc :
main:
@ Function supports interworking.
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 1, uses_anonymous_args = 0
@int main(void)
@{
@ initPIO_Port(PORT);
@ while (1) {
....
@ };
@}
stmfd sp!, {fp, lr}
add fp, sp, #4
ldr r0, .L13
bl initPIO_Port
.L12:
...
b .L12
initPIO_Port:
@ Function supports interworking.
@ args = 0, pretend = 0, frame = 8
@ frame_needed = 1, uses_anonymous_args = 0
@ link register save eliminated.
@ void initPIO_Port(AT91S_PIO *port)
str fp, [sp, #-4]!
add fp, sp, #0
sub sp, sp, #12 @ why subtract 12 - we're not using sp in following code ?
str r0, [fp, #-8] @ first empty place is at fp-8? fp points to last full location on stack - is this right ?
@ why is input parameter in r0 saved on stack and then read in r3 ?
ldr r3, [fp, #-8] @ port->PIO_PER=1<<PIN;
mov r2, #2
str r2, [r3, #0]
ldr r3, [fp, #-8] @ port->PIO_OER=1<<PIN;
mov r2, #2
str r2, [r3, #16]
add sp, fp, #0 @ previous value of sp
ldmfd sp!, {fp} @ restore fp
bx lr @ return
I've problem understanding behaviour of fp and sp register:
Why do I subtract 12 from sp and then don't use it? Why 12 ?
What exactly is the purpose of fp register ?
Why is r0 written on stack and read to r3 ? Aren't both meant to be for input parameters ?
Thanks for your help,
regards,
Rob.
Upvotes: 0
Views: 947
Reputation: 14359
It's somewhat depending on that the code is not (fully) optimized that makes it look rather confusing.
Why do I subtract 12 from sp and then don't use it? Why 12 ?
This is to allocate space for the stack frame, the reason it thinks it needs 12 bytes is that it will use one word to save the frame pointer, one word to store the local variable port
and one probably to save the return address (should it call another function).
What exactly is the purpose of fp register ?
It's the frame pointer. It uses this to access local variables. It's actually mostly redundant and may be optimized away if you enable optimizations.
One use of the frame pointer is that as you see the frame pointer of the calling frame is stored at offset 0
of the frame pointer. This means that you can follow the stack frames for debugging purposes.
Why is r0 written on stack and read to r3 ? Aren't both meant to be for input parameters ?
It's lack of optimization. r0
is the first input parameter, and it's stored in the frame allocated space for the port
variable, when the variable is being used it will be read from the frame. It's no problem to reuse r3
after doing this as the compiler would have saved the parameter passed in r3
to the frame allocated space for that parameter.
Again if you had turned on optimization the compiler would have realized that it wouldn't need to store the variable port
in the stack frame, it would let it live in r0
instead.
Upvotes: 1