Passing parameters and return values for a subroutine in assembly
When you pass back the return value in r0, the caller expects that you will do this. The caller does not expect that r0 will still contain the same value as the original first parameter, because r0 is specifically where the return value is.
Normally the ARM calling convention requires that the subroutine preserves r4 through r11, not r0 through r3. So there is no contradiction anyway.
Why not just try this yourself and see what the compiler does?
unsigned int fun ( unsigned int a, unsigned int b )
{
return(a+b);
}
compile to object and disassemble
arm-none-eabi-gcc -O2 -c fun.c -o fun.o
arm-none-eabi-objdump -D fun.o
and the result is
00000000 <fun>:
0: e0810000 add r0, r1, r0
4: e12fff1e bx lr
The two inputs a and b are passed in using r0 and r1. r0-r4 do not have to be preserved, in particular r0 because it is the return value cannot be preserved. So as the C code required the two operands are added together, and as the calling convention requires the result is returned in r0. r0 = r0 + r1.
The compiler has to conform to the convention otherwise the code it produces wont work so you can simply compile code and disassemble to find out quite a bit about the calling convention for a particular compiler and target.