I'm trying to understand the start and end of functions in ARM assembly:
PUSH {R0-R2, LR}
POP {R0-R2, PC}
Looking at this piece of code in IDA here's what I understood (Lets assume SP is 0x100):
PUSH R0 ; sp = 0xFC
PUSH R1 ; sp = 0xF8
PUSH R2 ; sp = 0xF4
PUSH LR ; sp = 0xF0
POP R0 ; sp = 0xF4
POP R1 ; sp = 0xF8
POP R2 ; sp = 0xFC
POP PC ; sp = 0x100
It seems like PC gets the value of R0, when it should get the value of LR.
Shouldn't PC get the value of LR?
When you PUSH or POP a bunch of registers, they always go into memory in the same relative positions, regardless of direction. The lowest-numberd register is stored at and loaded from the lowest address. So in this example everything will go back to the original register, except LR->PC.
To put that another way, imagine the PUSH as if it was storing {LR,R2,R1,R0}.
See the User Guide / Instruction Set reference for your favourite Arm 32-bit processor series; LDM and STM.