Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Some register calling conventions are dependent on the <a href="http://en.wikipedia.org/wiki/Application_binary_interface" rel="noreferrer">ABI</a> (Application Binary Interface). The <code>FP</code> is required in the <strong>APCS</strong> standard and not in the newer <strong>AAPCS</strong> (2003). For the <strong>AAPCS</strong> (GCC 5.0+) the <code>FP</code> does not <strong>have</strong> to be used but certainly can be; debug info is annotated with stack and frame pointer use for stack tracing and unwinding code with the <strong>AAPCS</strong>. If a function is <code>static</code>, a compiler really doesn't have to adhere to any conventions.</p> <p>Generally all ARM registers are <em>general purpose</em>. The <code>lr</code> (link register, also R14) and <code>pc</code> (program counter also R15) are special and enshrine in the instruction set. You are correct that the <code>lr</code> would point to <strong>A</strong>. The <code>pc</code> and <code>lr</code> are related. One is "where you are" and the other is "where you were". They are the <strong>code</strong> aspect of a function.</p> <p>Typically, we have the <code>sp</code> (stack pointer, R13) and the <code>fp</code> (<a href="https://stackoverflow.com/questions/10928646/whats-the-equivalent-of-bp-register-frame-pointer-on-arm-processors">frame pointer</a>, R11). These two are also related. This <a href="http://msdn.microsoft.com/en-us/library/ms253599%28v=vs.90%29.aspx" rel="noreferrer">Microsoft layout</a> does a good job describing things. The <em>stack</em> is used to store temporary data or <em>locals</em> in your function. Any variables in <code>foo()</code> and <code>bar()</code>, are stored here, <em>on the stack</em> or in available registers. The <code>fp</code> keeps track of the variables from function to function. It is a <em>frame</em> or picture window on the stack for that function. The <em>ABI</em> defines a layout of this <em>frame</em>. Typically the <code>lr</code> and other registers are saved here behind the scenes by the compiler as well as the previous value of <code>fp</code>. This makes a <em>linked list</em> of stack frames and if you want you can trace it all the way back to <code>main()</code>. The <em>root</em> is <code>fp</code>, which points to one stack frame (like a <code>struct</code>) with one variable in the <code>struct</code> being the previous <code>fp</code>. You can go along the list until the final <code>fp</code> which is normally <code>NULL</code>.</p> <p>So the <code>sp</code> is where the stack is and the <code>fp</code> is where the stack was, a lot like the <code>pc</code> and <code>lr</code>. Each old <code>lr</code> (link register) is stored in the old <code>fp</code> (frame pointer). The <code>sp</code> and <code>fp</code> are a <strong>data</strong> aspect of functions.</p> <p>Your point <strong>B</strong> is the active <code>pc</code> and <code>sp</code>. Point <strong>A</strong> is actually the <code>fp</code> and <code>lr</code>; unless you call yet another function and then the compiler might get ready to setup the <code>fp</code> to point to the data in <strong>B</strong>.</p> <p>Following is some ARM assembler that might demonstrate how this all works. This will be different depending on how the compiler optimizes, but it should give an idea,</p> <p><pre class="lang-none prettyprint-override"><code>; Prologue - setup mov ip, sp ; get a copy of sp. stmdb sp!, {fp, ip, lr, pc} ; Save the frame on the stack. <sup>See Addendum</sup> sub fp, ip, #4 ; Set the new frame pointer. ... ; Maybe other functions called here.<br> ; Older caller return <code>lr</code> stored in stack frame. bl baz ... ; Epilogue - return ldm sp, {fp, sp, lr} ; restore stack, frame pointer and old link. ... ; maybe more stuff here. bx lr ; return. </pre></code> This is what <code>foo()</code> would look like. If you don't call <code>bar()</code>, then the compiler does a <em>leaf optimization</em> and doesn't need to save the <em>frame</em>; only the <code>bx lr</code> is needed. Most likely this maybe why you are confused by web examples. It is not always the same.</p> <p>The take-away should be,</p> <ol> <li><code>pc</code> and <code>lr</code> are related <strong>code</strong> registers. One is "Where you are", the other is "Where you were".</li> <li><code>sp</code> and <code>fp</code> are related <strong>local data</strong> registers.<br/>One is "Where local data is", the other is "Where the last local data is".</li> <li>The work together along with <a href="https://stackoverflow.com/questions/261419/arm-to-c-calling-convention-registers-to-save">parameter passing</a> to create <em>function</em> machinery.</li> <li>It is hard to describe a general case because we want compilers to be as <strong>fast</strong> as possible, so they use every trick they can.</li> </ol> <p>These concepts are generic to all CPUs and compiled languages, although the details can vary. The use of the <em>link register</em>, <em>frame pointer</em> are part of the <a href="http://en.wikipedia.org/wiki/Function_prologue" rel="noreferrer">function prologue</a> and epilogue, and if you understood everything, you know how a <em>stack overflow</em> works on an ARM.</p> <p>See also: <a href="https://stackoverflow.com/questions/261419/arm-to-c-calling-convention-registers-to-save">ARM calling convention</a>.<br/> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://msdn.microsoft.com/en-us/library/aa448593.aspx" rel="noreferrer">MSDN ARM stack article</a><br/> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.cl.cam.ac.uk/~fms27/teaching/2001-02/arm-project/02-sort/apcs.txt" rel="noreferrer">University of Cambridge APCS overview</a><br/> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://minghuasweblog.wordpress.com/2013/04/05/arm-cc-software-stack-back-trace/" rel="noreferrer">ARM stack trace blog</a><br/> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="https://developer.apple.com/library/ios/documentation/Xcode/Conceptual/iPhoneOSABIReference/Articles/ARMv6FunctionCallingConventions.html" rel="noreferrer">Apple ABI link</a><br/></p> <p>The basic frame layout is,</p> <ul> <li>fp[-0] saved <code>pc</code>, where we stored this frame.</li> <li>fp[-1] saved <code>lr</code>, the return address for this function. </li> <li>fp[-2] previous <code>sp</code>, before this function <em>eats</em> stack.</li> <li>fp[-3] previous <code>fp</code>, the last <em>stack frame</em>.</li> <li>many optional registers...</li> </ul> <p>An <strong>ABI</strong> may use other values, but the above are typical for most setups.</p> <p><strong>Addendum:</strong> This is not an error in the assembler; it is normal. An explanation is in the <a href="https://stackoverflow.com/questions/32623597/arm-gcc-generated-functions-prolog">ARM generated prologs</a> question.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload