590 likes | 768 Views
Stacks and Frames. Memory Stacks Frames Automatic Variables. Memory. SPARC architecture has a 32 bit address register Provides 0x100,000,000 byte-addressable units of memory or 4,294,967,296 (2 32 ) bytes of memory (4 Gigabytes) Data may be stored in memory using Byte .byte 1 byte
E N D
Stacks and Frames Memory Stacks Frames Automatic Variables
Memory • SPARC architecture has a 32 bit address register • Provides 0x100,000,000 byte-addressable units of memory or 4,294,967,296 (232) bytes of memory (4 Gigabytes) • Data may be stored in memory using • Byte .byte 1 byte • Half-word .half 2 bytes • Word .word 4 bytes • Double .double 8 bytes
Memory alignment • All memory references must be aligned • A byte can have any address • A half word must have an even address • A full word must have an address divisible by 4 • A double word must have an address divisible by 8
Program Address Space Low memory Code Section Code Static variables OS information Heap Section Dynamic variables Stack Section Automatic variables High memory
Stack section • Contains automatic variables of the functions • Contains frame information for each call of a function • Stack grows from high memory to low memory • Really a stack of Frames
Stack View Stack Top %sp -> Low memory Function Frame 3 Function Frame 2 Function Frame 1 High memory Main Frame
Stack Addresses • The stack is a stack of double words • Therefore, the stack pointer, register %o6 or %sp, must always be divisible by 8 • This is accomplished by the save instruction • save %sp, value & -8, %sp
The Frame (1) Stack Top %sp -> Low memory High memory Frame Ptr %fp ->
The Frame (2) Stack Top %sp -> <- 64 bytes for register window set 4 bytes for return structure address -> <- 24 bytes for first six function parameters Storage for Local variables -> <- 16 bytes for Compiler stuff Frame Ptr %fp ->
The Frame Size • Therefore the frame size is always (-108 - local_storage) & -8 • The minus sign is used because the stack grows from high memory to low memory save %sp, (-108 - local_storage) & -8, %sp new sp = old_sp + (– 108 – local_storage) & -8 new_fp = old_sp
Addressing Frame Components • You never need to address the data in the register window set. The OS uses this • The addresses of the return structure and parameters are referenced using the stack pointer, %sp Those references are positive from the %sp • The addresses of automatic variables, i.e. local variables use the frame pointer, %fp Those references are negative from the %fp
Example • Consider the C declarations: int x, y; char ch; double f; • x and y take 4 bytes each • ch takes one byte • f takes 8 bytes • Storage starts at %fp -20
Addressing Local Variables(1) • All automatic (local) variables are referenced using the frame pointer and their offsets (negative) from the frame pointer • We define constants that represent their offsets • define ( x, -20) • define (y, -24) • define (ch, -36) // could use 35, 34, 33 • define (f, -32)
Loading Local Variables(1) • To load the variable x into %o0, we use the following instruction ld [%fp + x], %o0 • To load the variable ch into %l0, we use the following instruction ldub [%fp + ch], %l0
Loading Local Variables(2) • To load the variable f into %o0 and %o1, we use the following instruction ldd [%fp + f], %o0 Note: This instruction loads register %o0 with contents of f and register %o1 with contents f+4
Storing Local Variables(1) • To store the variable x from %o0, we use the following instruction st %o0, [%fp + x] • To store the variable ch from %l0, we use the following instruction stb %l0, [%fp + ch]
Storing Local Variables(2) • To store the variable f from %o0 and %o1, we use the following instruction std %o0, [%fp + f] Note: This instruction stores register %o0 into f and register %o1 into f+4
Sample Program addxy.m /******************************************************* * File: addxy.m * Dir: cis235/suns/ch05 * Date: February, 1999 * Modified: March 2001 * Author: HGG * Computer: KUNET suns * Assembler: sa addxy * Compile: gcc * Execute: a.out * Purpose: To demonstrate local variables. Read * two integers x and y, add them, * put the result in sum and print * everthing out. *******************************************************/
addxy.m (1) .data .align 8 prompt: .asciz "Enter two integers (^D to quit): " . align 8 formati: asciz "%d %d" . align 8 formato: .asciz "x = %d, y = %d, sum = %d\n" .align 4 ! automatic data for a program define(x, -20) define(y, -24) define(sum, -28)
addxy.m (2) .text .align 4 .global main main: save %sp, (-108 - 12) & -8, %sp loop: !while (printf(prompt), sethi %hi(prompt), %o1 call printf,0 or %o1, %lo(prompt), %o0
addxy.m (3) ! scanf(formati, &x, &y) == 2) set formati, %o0 ! formati address in o0 add %fp, x, %o1 ! address of x into o1 call scanf,0 add %fp, y, %o2 ! address of y into o2 cmp %o0, 2 ! 2 integers read? bne done nop
addxy.m (4) NOTE how x and y are loaded from memory ! sum = x + y; ! o1 = x o2 = y ld [%fp + x], %o1 ld [%fp + y], %o2 add %o1, %o2, %o3 st %o3, [%fp + sum] ! leave in o's for printf
addxy.m (4) ! printf(formato, x, y, sum) sethi %hi(formato),%l1 call printf,0 or %l1,%lo(formato),%o0 b loop nop done: ! exit call exit, 0 mov 0, %o0
Exercise • Modify your field extraction program so that the variables of integer, lsb, nob are local variables. • Due date: Monday April 2
Array Storage • Consider an array A in C defined as follows: some_type A[array_size] The compiler needs to set aside enough storage for the entire array. The following formula is used by the compiler: bytes_needed = array_size * size of some_type
Examples Assume automatic storage is desired • int a[10] requires 40 bytes • double f[25] requires 200 bytes • char ch[25] usually requires 28 bytes (why?) • customertype customers[100] requires 8000 bytes assuming a customertype needs 80 bytes.
Array Addressing • Once stored, how is the address of a component computed. • Depends on how the elements are stored: big-endian little-endian • Big-endian stores the low index in lower memory and the higher indices in high memory • Little-endian stores the low index in high memory and the high indices in low memory • Comes from the way numbers are stored
Big-endian vs Little-endianStoring 0x12345678 Low memory Big-Endian Little-Endian High memory
Big-endian vs Little-endian Low memory High memory Big-Endian Little-Endian
Big Endian Array Storage • Most compiler store arrays in big endian order • Address of a component A[I] is then computed using the following formula: address(A[i]) = address(A) + i*(size of component)
Computing Address of A[i] Address of A i components Address of A[I] Size of 1 component
Example • Suppose we have the following definitions in C: int sum; int A[10]; int i; • In assembler we could have the offsets: define(sum, -20) define(A, -60) define(i, -64)
Example (con’t) The address of A[i] is given by address(A[i]) = address(A) + i * 4 Assembler code for the address: add %fp, A, %l0 ! Address of A ld [%fp + I], %l1 ! Value of i sll %l1, 2, %l2 ! Multiply by 4 add %l1, %l2, %l3 ! Address of A[i]
Looping Thru an Array Consider the code sum = 0; for(i = 0; i < 10; i++) sum = sum + A[i]; We use the computation of the address of A[i] to write the assembler code for the loop
Assembler Code for Loop clr %l0 ! sum clr %l1 ! i loop: cmp %l1, 10 bge done nop add %fp, A, %o0 ! %o0 = addr(A) sll %l1, 2, %l2 ld [%o0+ %l2], %o1 !%o1 = A[i] add %l0, %o1, %l0 !sum += A[i]; inc %l1 ! i++ b loop nop done: st %l0, [%fp + sum] st %l1, [%fp + i]
Example • Write an assembler program to read in an array of 10 integers and write them out.
arr.m (1) .data .align 8 prompt: .asciz "enter ten numbers: " .align 8 frmti: .asciz "%d" .align 8 frmto: .asciz "The value is %d\n"
arr.m (2) define(i, -20) ! i - loop control variable define(A, -60) ! the array A .align 4 .text .global main main: save %sp, (-108 - 44) & -8, %sp
arr.m (3) ! printf(prompt); sethi %hi(prompt), %o0 call printf, 0 or %o0, %lo(prompt), %o0 !***************************** ! for(i = 0;1 < 4; i++) ! scanf(frmti, &A[i]); mov 0, %l0 ! i = 0; st %l0, [%fp + i]
arr.m (4) loop1: ! scanf(frmti, &A[i]) set frmti, %o0 add %fp, A, %o2 ! the address of A ld [%fp+i], %o1 sll %o1, 2, %o1 ! 4 * i add %o2, %o1, %o1 ! the addr( A[i] ) call scanf, 0 nop
arr.m (5) ! i++ ; i < 10? ld [%fp+i], %l0 inc %l0 st %l0, [%fp+i] cmp %l0, 10 bl loop1 nop
arr.m (6) !**************************** ! for(i = 0;1 < 10; i++) ! printf(frmto, A[i]); mov 0, %l0 ! i = 0; st %l0, [%fp + i]
arr.m (7) loop2: ! printf(frmto, A[i]) != 1 set frmto, %o0 add %fp, A, %o2 ! the address of A ld [%fp+i], %o1 ! %o1 = i sll %o1, 2, %o1 ! %o1 = 4 * i add %o2, %o1, %o1 ! address of A[i] ld [%o1], %o1 ! contents of A[i] call printf, 0 nop
arr.m (8) ! i++ ; i < 10? ld [%fp+i], %l0 inc %l0 st %l0, [%fp+i] cmp %l0, 10 bl loop2 nop
arr.m (9) call exit,0 mov 0, %o0
Structures A structure is similar to a class, where all data members are public. In C structures do not have member functions. The data members of a structure are stored as a composite unit. Each member has a address (offset) measured from the beginning of the structure
Example Consider the customer structure defined below: typedef struct { char name[24]; int age; int salary; } customer_type; customer_type customer;
Addressing Structure Components To address a component of a structure, we use the formula: addr(component) = addr(structure) + offset of component from beginning of structure It is customary to use Big Endian storage for structures, so the offset is positive.
customer Customer Low memory Offset of name: 0 Offset of age: 24 Offset of salary: 28 High memory