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.
A POP instruction with PC in its register list is a branch instruction to the value being popped out of the stack. So for
POP {R0, PC} ~= MOV PC,R0 ; Except that R0 is on the stack
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With