Category:ARM Assembly: Difference between revisions

Line 150:
===Call Stack===
Most processors, including the x86 family, will use the same hardware stack for function arguments, local variables, and return addresses. The ARM doesn't actually need to store a return address onto the stack until subroutines are nested (though ARM Assembly written by a compiler will most likely do so anyway.) This is because the <i>link register</i> or <code>r13</code> is responsible for holding the return address. <code>BL</code> is the equivalent of <code>CALL</code> on the x86 architecture, and instead of pushing the program counter to the stack, it gets copied to the link register before the branch. Once the function is complete, execution returns by moving the value in the link register back into the program counter. For nested subroutines, the link register will need to be pushed onto the stack, as the link register can only "remember" the return address of the most recent <code>BL</code> instruction.
 
Actually using the stack to save registers and retrieve them has somewhat strange syntax. I'd recommend using the ''unified syntax'' option if your assembler has it - which lets you use the simple <code>PUSH</code> and <code>POP</code> commands to back up and restore register contents. Normally, these two instructions are only valid in THUMB mode, but with unified syntax you can use them in 32-bit ARM programming as well. Arguments for the <code>PUSH</code> and <code>POP</code> instructions are all enclosed in curly braces, and separated by dashes to specify a range of registers, or commas to separate individual registers. It doesn't matter what order you type them in - they all get pushed/popped in the same order regardless. Standard calling conventions dictate that the stack shall be aligned to 8 bytes at all times - in order to do this, always push/pop an even number of registers, even if you end up having to push/pop one more than necessary. It won't hurt anything if you do, as long as you put it back where you got it.
 
<lang ARM Assembly>PUSH {R4,R5,R6,R7} ;the contents of these registers are stored on the stack.
POP {R4,R5,R6,R7} ;you don't need to list these in reverse order like you would on x86 - the assembler takes care of that for you.</lang>
 
If you don't have unified syntax, you'll need to use the commands below for 32-bit ARM. (<code>PUSH</code> and <code>POP</code> are valid in THUMB mode even if you don't have unified syntax.)
<lang ARM Assembly>STMFD sp!,{r0-r12,lr} ;equivalent of PUSH {r0-r12,lr}
LDMFD sp!,{r0-r12,lr} ;equivalent of POP {r0-r12,lr}</lang>
 
===Limitations of the ARM===
1,489

edits