Memory and Stack
E N D
Presentation Transcript
Memory and Stack Assembly Language
Memory • In SPARC, there are only 32 registers. • Not enough to hold all data for computation. • We use memory to store variables. • Variables in memory can be: C SPARC bits char byte 8 short halfword 16 int, long word 32 Assembly Language
Memory • All variables in memory must be “aligned”. • A “short” variable is 16-bit long or halfword (2 bytes) • It must be stored in the addressed that are divisible by “two”, or “even address” (aligned to two-byte boundary) • For example, 0, 2, 4, …, 1024, 1026, etc. • An “int” variable is 32-bit long or one word (4 bytes) • It must be stored in the addressed that are divisible by “four”. (aligned to four-byte boundary). • For example, 0, 4, 8, …, 1024, 1028, etc. • This is for efficiency in hardware. Assembly Language
Memory • The SPARC architecture is big endian. • Store LSB (the smallest-numbered byte) at the first address. • For example: to store a short variable containing 0x0932 at address 1026 (must be aligned!) • 0x32 (LSB) is stored at address 1026. • 0x09 (MSB) is stored at address 1027. • Note: an instruction must be word-aligned. Why ? Assembly Language
The Stack • We store automatic or “local” variables in the memory called “Stack”. • An automatic variable is a variable that is accessible only inside a function. int g; int main() { int i, j; ... } Global var Local vars Assembly Language
The Stack Pointer • The stack is last-in-first-out (LIFO). • Each program has its own private stack. • %o6 aka. %sp is the stack pointer. • Stack is located near the top of memory (biggest addressed). • When the stack grows, the %sp decreases. • When the stack shrinks, the %sp increases. • Thus to get more spaces in the stack, we subtract the number of bytes from the stack pointer. Assembly Language
To get 64 bytes more: Sub %sp, 64, %sp The Stack Pointer Assembly Language
The Stack Pointer • The stack must be doubleword (8-byte) aligned. • Thus, the address must be divisible by eight. • If we want 94 bytes, we must ask for 96 bytes to keep the stack aligned. • Thus: sub %sp, 96, %sp • Or we can: add %sp, -94 & -8, %sp • Why -94&-8 ? Check out two’s complement. Done by assembler* Assembly Language
The Frame Pointer • The stack pointer is always changed as more variables are needed. • How can we refer to a variable ? • Use the frame pointer, %fp or %i6. • The frame pointer remains fixed for each subroutine. • At the beginning of the program, we execute a “save” instruction to allocate space in the stack. Assembly Language
Frame and Stack Pointers • Subroutine A calls B: int A() { ... B(); ... } int B() { ... } Before Call After Call Assembly Language
Save Instruction • The save instruction must allocate space for both local variables and registers. • Must allocate 64 bytes + spaces for variables. save %sp, -64-bytes_for_vars, %sp • Suppose we want to store five “int” (4-byte) variables (var0 - var4): save %sp, (-64-(5*4)) & -8, %sp • This is actually: save %sp, -88, %sp Assembly Language
Save Instruction Assembly Language
Addressing Stack Variables • As SPARC is the load-store architecture, we cannot compute variables data from the stack directly. • We must load them to registers, compute, and then store back to the stack. • Remember all variables must be aligned based on its size. • SPARC has different load/store instructions for each type. Assembly Language
Load Instructions • ldsb - load signed byte, propagate sign. • ldub - load unsigned byte, clear high 24 bits of register. • ldsh - load signed halfword, propagate sign. • lduh - load unsigned halfword, clear high 16 bits of register. • ld - load word • ldd - load double, register number even, first four bytes into register n, next four into register n+1. Assembly Language
Load Instructions ld [%fp - 4], %l1 ! Load var0 into %l1 ld [%fp - 8], %o2 ! Load var1 into %o2 mov -16, %l4 ld [%fp + %l4], %l3 ! Load var3 into %l3 ldd [%fp - 16], %g2 ! Load var3 into %g2 ! and var2 into %g3 ldd [%fp - 16], %l5 ! Illegal, why ? Assembly Language
Store Instructions • stb - store low byte of register, bits 0 - 7 into memory. • sth - store low two bytes of register, bits 0 - 15 into memory. • st - store register. • std - store double, register number even, first four bytes from register n, next four from register n+1. Assembly Language
Store Instructions st %l1, [%fp - 4] ! Store %l1 into var0 st %o2, [%fp - 8] ! Store %o2 into var1 sth %l4, [%fp - 6] ! Store halfword of %l4 sth %l4, [%fp - 9] ! Illegal, why ? st %o2, [%fp - 4 + %l2] ! Illegal, why ? st %o2, [%fp - 5120] ! Illegal, why ? Assembly Language
Variable Offsets in Stack • We use the frame pointer as the base reference to variables in the stack. • All variables must be properly aligned. • Example: int a, b; // 4 bytes each char ch; // 1 byte short c, d; // 2 bytes each unsigned e; // 4 bytes Assembly Language
Variable Offsets in Stack a: %fp - 4 b: %fp - 8 ch: %fp - 9 c: %fp - 12 d: %fp - 14 e: %fp - 20 Assembly Language
Actual Addresses Assembly Language
Offsets and Stack Allocation • Use macro to arrange the offsets define(a_s, -4) define(b_s, -8) define(ch_s, -9) define(c_s, -12) define(d_s, -14) define(e_s, -20) • Allocate spaces on stack: save %sp, ((-64 - 20) & -8), %sp ==> save %sp, -84 & -8, %sp ==> save %sp, -88, %sp Assembly Language
Manipulate Variables in Stack • To load and store ld [%fp + a_s], %l0 ldub [%fp + ch_s], %l1 ! char type is unsigned. ldsh [%fp + d_s], %l2 ! short type is signed. ld [%fp + e_s], %l3 • To compute: b = a + c; ld [%fp+a_s], %l0 ldsh [%fp+c_s], %l1 add %l0, %l1, %l2 st %l2, [%fp+b_s] Assembly Language
Variables in Registers • Some variables are used very often. • Loop counters • We can use registers to hold their values instead of using stack. • In C, we use a keyword “register”. register int i; // i is in a register. • When referred to these variables, we use values from registers directly. Assembly Language
Variables in Registers int a, b; register int j, k; int x, y; • Only a, b, x, and y are in the stack. • j and k are in registers. define(a_s, -4) define(b_s, -8) define(x_s, -12) define(y_s, -16) define(j_r, l0) define(k_r, l1) Assembly Language
Variables in Registers • To compute: j = 19; a = 8; y = j - 3 + a; • Note: we use %l2 and %l3 as temporary registers. mov 19, %j_r mov 9, %l2 st %l2, [%fp+a_s] sub %j_r, 3, %l2 ld %l3, [%fp+a_s] add %l2, %l3, %l2 st %l2, [%fp+y_s] Assembly Language
main() { int a, b, c; register int i; i = 0; a = 100; b = 15; c = 0; while(i < 20) { c += a - b; a--; i = i + 2; } } Our Fourth Program Assembly Language
Our Fourth Program define(a_s, -4) define(b_s, -8) define(c_s, -12) define(i_r, l0) .global main main: save %sp, (-64 + -12) & -8, %sp clr %i_r ! i = 0; mov 100, %l1 st %l1, [%fp + a_s] ! a = 100; mov 15, %l1 st %l1, [%fp + b_s] ! b = 15; Assembly Language
Our Fourth Program clr %l1 st %l1, [%fp + c_s] ! c = 0; loop: cmp %i_r, 20 bge done nop ld [%fp + a_s], %l1 ld [%fp + b_s], %l2 sub %l1, %l2, %l3 ! a - b ld [%fp + c_s], %l1 add %l1, %l3, %l1 ! c + a - b st %l1, [%fp + c_s] ! c += a - b; Assembly Language
Our Fourth Program ld [%fp + a_s], %l1 sub %l1, 1, %l1 st %l1, [%fp + a_s] ! a--; add %i_r, 2, %i_r ! i = i + 2 ba loop nop done: mov 1, %g1 ta 0 Assembly Language