banner



Which Register Holds Frame Pointer

\(\newcommand{\doubler}[ane]{2#one} \newcommand{\binary}{\mathtt} \newcommand{\hex}{\mathtt} \newcommand{\octal}{\mathtt} \newcommand{\prog}{\mathtt} \newcommand{\lt}{<} \newcommand{\gt}{>} \newcommand{\amp}{&} \)

Nosotros have seen that nosotros can allocate memory space on the stack by subtracting the number of bytes from the stack pointer, since the stack grows toward lower memory addresses. We can then save values on the stack in this newly allocated memory expanse. Once we take retrieved the saved values, we deallocate the stack memory area by only adding the number of bytes to the stack pointer.

In this department, we await at a way to use stack memory for local variables. We could use push and pop, but if the algorithm requires a value that is non at the elevation of the stack, I am certain you realize that it would be very tedious to keep track of where all the values are at each point in execution of the office.

Instead, we will create local variables on the stack in the same style we stored saved values at that place, past merely subtracting the number of bytes required by each variable from the stack pointer. This does not store whatsoever data in the variables, information technology simply sets aside retention that we tin can use. (Perhaps you have experienced the mistake of forgetting to initialize a local variable in C!)

Next, nosotros accept to figure out a mode to admission the variables in this reserved data area on the stack. In that location are no labels in this area of retention, and then nosotros cannot straight utilize a proper noun like we did when accessing memory in the .rodata segment.

A much simpler solution is to establish a point on the stack and use this address to straight access values on the stack relative to this address. It may seem tempting to use the stack pointer every bit the reference pointer, but this creates complications if we wish to use the stack within the part.

Subsection 10.five.1 The Frame Pointer

Now yous know the purpose of the Frame Pointer. Each function has control over an expanse on the stack, its Stack Frame. The frame pointer register, fp, contains an address that serves every bit a reference indicate for the stack frame. Items that are stored in the stack frame tin be readily accessed relative to the frame arrow using the offset forms of the str and ldr instructions. To see how this is done, let us render to the C program in Listing ii.15.ii and expect at the compiler-generated assembly language in Listing 10.five.1.

                    .arch   armv6         .file   "echoChar1.c"         .department  .rodata         .align  2 .LC0:         .ascii  "Enter one character: \000"         .align  two .LC1:         .ascii  "You entered: \000"         .text         .align  2         .global primary         .syntax unified         .arm         .fpu    vfp         .type   main, %function main:         @ args = 0, pretend = 0, frame = viii         @ frame_needed = one, uses_anonymous_args = 0         push button    {fp, lr}         add     fp, sp, #4      @@ fix our frame pointer         sub     sp, sp, #viii      @@ allocate memory for local var         mov     r2, #21         ldr     r1, .L3         mov     r0, #1         bl      write           @@ prompt user for input         sub     r3, fp, #5      @@ compute address         mov     r2, #1          @@ ane char         mov     r1, r3          @@ accost for storing input char         mov     r0, #0          @@ standard in (keyboard)         bl      read         mov     r2, #13         @@ nice message to user         ldr     r1, .L3+4         mov     r0, #1         bl      write         sub     r3, fp, #5      @@ address where char was stored         mov     r2, #1         mov     r1, r3         mov     r0, #1         bl      write         mov     r3, #0         mov     r0, r3         sub     sp, fp, #4      @@ deallocate local var         @ sp needed      popular        {fp, pc} .L4:         .align  ii .L3:         .discussion   .LC0         .word   .LC1         .size   principal, .-chief         .ident  "GCC: (Raspbian 6.3.0-xviii+rpi1) 6.iii.0 20170516"                  
Listing ten.5.1. Echoing single characters entered on the keyboard. (gcc asm).

You learned in Section 8.v that when reading from the keyboard we need to pass an address of a retentiveness location to the reading function. In that Section we were using scanf, but the same holds truthful for read. So we need a local variable to hold the character. The memory for this local variable is allocated on the stack with the educational activity:

sub     sp, sp, #8      @@ allocate memory for local var                

This simply moves the stack arrow eight bytes. It may seem wasteful to classify viii bytes when merely one byte is needed for a char variable. The protocol specification, Process Call Standard for the ARM Architecture[three], provides ii constraints on the stack pointer:

  1. The stack pointer must always be aligned to a word (4 bytes) boundary.

  2. The stack pointer must be double-discussion (8 bytes) aligned at a "public interface."

"Public interface" essentially means a global function that can be called from anywhere in the program. For example, this function calls write and read, which are functions in the C libraries. All the functions used in this book are public, so e'er align the stack pointer on 8-byte boundaries. This precaution has no effect on performance, but not doing information technology has the potential of creating obscure bugs in your programme.

The location in the stack frame for storing the input character is computed relative to the frame pointer:

sub     r3, fp, #5      @@ compute address                

This educational activity subtracts \(5\) from the address in the frame pointer register and stores the result in register r3, ready to be passed to the read function.

Let us switch to my assembly language solution, List 10.5.ii for farther explanation of how this code works.

@ echoChar2.s @ Prompts user to enter a character and echoes it. @ 2017-09-29: Bob Plantz  @ Define my Raspberry Pi         .cpu    cortex-a53         .fpu    neon-fp-armv8         .syntax unified         @ mod syntax  @ Useful source code constants         .equ    STDIN,0         .equ    STDOUT,1         .equ    aLetter,-five         .equ    local,8  @ Abiding program information         .section  .rodata         .align  2 promptMsg:         .asciz	 "Enter 1 character: "         .equ    promptLngth,.-promptMsg responseMsg:         .asciz	 "You entered: "         .equ    responseLngth,.-responseMsg  @ Program code         .text         .align  2         .global main         .blazon   main, %function main:         sub     sp, sp, 8       @ space for fp, lr         str     fp, [sp, 0]     @ relieve fp         str     lr, [sp, 4]     @   and lr         add     fp, sp, four       @ gear up our frame pointer         sub     sp, sp, local   @ allocate retentiveness for local var          mov     r0, STDOUT      @ prompt user for input         ldr     r1, promptMsgAddr         mov     r2, promptLngth         bl      write          mov     r0, STDIN       @ from keyboard         add     r1, fp, aLetter @ address of aLetter         mov     r2, 1           @ ane char         bl      read          mov     r0, STDOUT      @ nice message for user         ldr     r1, responseMsgAddr         mov     r2, responseLngth         bl      write          mov     r0, STDOUT      @ echo user'due south grapheme         add     r1, fp, aLetter @ address of aLetter         mov     r2, 1           @ one char         bl      write          mov     r0, 0           @ render 0;         add     sp, sp, local   @ deallocate local var         ldr     fp, [sp, 0]     @ restore caller fp         ldr     lr, [sp, 4]     @       lr         add together     sp, sp, eight       @   and sp         bx      lr              @ return  @ Addresses of messages         .align  2 promptMsgAddr:         .word   promptMsg responseMsgAddr:         .word   responseMsg                
Listing 10.5.two. Echoing single characters entered on the keyboard. (prog asm).

The first affair to observe is that I take divers several symbols using the .equ directive to make it easier to read the lawmaking.

.equ    STDIN,0 .equ    STDOUT,one .equ    aLetter,-5 .equ    locals,viii                

STDIN and STDOUT are good names for the keyboard and screen file numbers.

Like the gcc compiler, I utilise the byte at \(-5\) from the frame pointer equally the char variable to shop the input graphic symbol. I know that local variables are always at negative offsets from the frame pointer, and then I ascertain the symbolic name, aLetter, as a negative value. Be conscientious to notice that the values of offsets for the local variables need to take into account the registers that will be saved on the stack. These offsets are relative to the frame pointer, fp, which points to a identify on the stack "below" the saved registers.

And since this is the place where I am defining the local variable offset, it is a expert place to also compute and define the corporeality of (properly aligned) stack space needed for the local variable(s). I called this constant locals. It is the corporeality that needs to be subtracted from sp.

I also recognize that when I call the read function, the accost of aLetter needs to be in r1. So instead of using r3 for the computation then moving information technology to r1, I compute it straight into r1:

add     r1, fp, aLetter    @ address of aLetter                

Y'all may wonder why the addresses of the two letters are non placed in the .rodata department since they should not be changed by the program. The answer is related to the machine code for the ldr pedagogy. All ARM instructions are 32 bits long. Role of those 32 bits need to exist used to define the education, then the space left for specifying the accost is less than 32 bits long. The course of the ldr pedagogy in this program uses pc-Relative Addressing. The number that gets stored as part of the ldr teaching is the distance, in bytes, from the location of the instruction to the location of the 32-flake data (in this case, an accost) that the program needs. When the operating arrangement loads a plan into memory, nosotros take no mode of knowing where the .rodata section will be located in memory relative to the .text section. So the assembler cannot compute the distance from the ldr instruction to the location where the address of the text string is stored. By placing this location in the .text segment (along with the instructions) the assembler can compute the distance. We will get into more detail in Chapter 11.

Subsection 10.5.2 Designing the Prologue and Epilogue

Figure 10.5.3 shows the state of our stack frame after executing the prologue instructions:

main:         stmfd   sp!, {fp, lr}   @ salvage caller's info         add     fp, sp, 4       @ ready up our frame pointer         add     sp, sp, locals  @ allocate retentiveness for local var                
Figure x.v.3. The local variable in the programme from List 10.5.2 is allocated on the stack. Numbers on the left are offsets from the accost in the frame pointer (fp) register.

To generalize:

stmfd   sp!, {<registers>}   @ relieve caller's info add     fp, sp, <m>          @ gear up upwardly our frame pointer sub     sp, sp, <n>          @ allocate retentivity for local var                

where <…> are values you lot demand to provide. These three instructions make upwardly the prologue to the function:

  1. Save the lr (return address) and fp (caller's frame pointer), plus any other regiters that need to exist saved (Tabular array 10.1.1), on the stack. The registers are specified in the register listing, {<registers>}.

  2. Constitute the frame pointer for this role. Add together \(chiliad = 4 \times (r - one)\) to the address in the sp, where \(r\) is the number of registers saved on the stack. This ensures that the frame pointer will point to the return address.

  3. Allocate memory on the stack for the local variables in this role. The number subtracted from the sp, \(n\text{,}\) must meet 2 criteria:

    1. \(n \geq \) total number of bytes required past local variables.

    2. \((thousand + northward + 4)\) is a multiple of \(eight\text{.}\)

I strongly urge you to describe pictures similar Figure 10.5.3 when designing your stack frame. It is the but way I am able to become all the numbers to be correct, and I have been designing stack frames for over forty years.

I mention at this point that arithmetic/logic expressions tin be used to automatically compute the values of symbols in .equ statements. I would do this in a production environment, simply such automation tends to mask the basic concepts. Helping y'all learn the basic concepts is the whole point of this volume, so I recommend that you avoid such automation. Another reason for fugitive it is that when at that place is a fault in the automation expressions, it is much more hard to debug it.

At this point in the function, the stack frame is treated as a tape (or struct in C), with the frame pointer used every bit the reference point. When determining the offsets from the fp to locations of local information in the stack frame, think to have into account the memory that is occupied past the saved register values. Thus the first available byte for local variables is \(-5\) from the fp. Records are discussed in more than detail in Section fifteen.3.

The current location of the stack pointer is considered as the "bottom" of the stack during the rest of this function.

After this role has performed its work nosotros deallocate the local variables area on the stack by moving the stack arrow, sp. Then nosotros restore the register values that were saved on the stack:

add together     sp, sp, local   @ deallocate local var ldmfd   sp!, {fp, lr}   @ restore caller's info                

These two instructions make up the epilogue of the function:

  1. Referring to Figure 10.five.4, subtracting \(n\) from the address in the stack pointer will identify it and so it at present points at the registers we saved and then they tin be restored. At this point, the values "above" the stack arrow are considered invalid, and thus, deallocated.

  2. The second pedagogy pops 2 values off the top of the stack into:

    1. the frame pointer, and

    2. the link register.

    This restores the calling function's value in the frame arrow and return address.

The land of the stack after deallocating the local variables, but before restoring annals contents, is shown in Figure 10.5.4.

Figure 10.5.four. Local variable stack area in the program from List 10.5.2 before restoring the caller's frame pointer and the link register. Although the values in the grayness area may remain they are invalid; using them at this point is a programming mistake.

It is important to understand that although you know the values higher up the stack pointer (the gray expanse in Effigy 10.five.4) are probably even so in memory, attempting to access them is a violation of stack protocol.

Yous may wonder why my epilogue and return:

add together     sp, sp, local   @ deallocate local var ldmfd   sp!, {fp, lr}   @ restore caller's info bx      lr              @ return                

differs from the epilogue and return that the compiler generated:

sub     sp, fp, #iv      @@ deallocate local var ldmfd   sp!, {fp, pc}                

I believe that my style makes the prologue and epilogue more symmetrical, thus less prone to errors. In my view, that outweighs the extremely pocket-sized toll of calculation one more didactics.

Which Register Holds Frame Pointer,

Source: https://bob.cs.sonoma.edu/IntroCompOrg-RPi/sec-varstack.html

Posted by: thornecovioll59.blogspot.com

0 Response to "Which Register Holds Frame Pointer"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel