Вы находитесь на странице: 1из 41

Information Technology

FIT1008/1054/2085 Lecture 7
Prepared by: M. Garcia de la Banda
based on D. Albrecht, J. Garcia

Local Variables in MIPS

Prepared by:
Maria Garcia de la Banda
Where are we at:
§ We have seen the basics of:
– MIPS architecture
– MIPS Instruction set (the subset we will use)
– Storing and accessing global variables
– Compiling basic arithmetic, selection and loops into
assembler
– Creating and accessing arrays of integers
FLUX: IJ8V2X
§ Consider the following memory state, where a is a
global variable pointing to an array. How many
elements does the array have?
A) 6
B) 5
C) 3
D) None of the above

3
FLUX: IJ8V2X
§ Consider the same memory state. Where are the
elements of the array in memory?
A) Text segment
B) Static part of the Data segment
C) Heap segment
D) Stack segment
E) None of the above

4
FLUX: IJ8V2X
§ Assume a and i are global variables representing an
array and an integer. What is the following MIPS code
trying to do:

A) Read a[i] lw $t0, a


lw $t1, i
B) Read a[i*2] addi $t2, $0, 4
mult $t1, $t2
C) Read a[i*4]
mflo $t1
D) None of the above add $t1, $t1, $t0
lw $t2, 4($t1)

5
Learning objectives for this lecture:
§ To understand how to compile local variables in MIPS
and why
§ To achieve this we will discuss:
– The need for memory diagrams and how to draw them
– How the system stack works and the role played by $sp
and $fp
– How (and why) local variables are stored on the stack and
how to access them
– How to use addressing modes to access variables

6
Again, we are assuming numbers
appear directly at the memory
location (not true in Python, but true
Memory diagrams in C or Java) and occupy 4 bytes

§ Useful for humans to know how to access variables


§ Show memory allocated to variables
– Addresses Contents (some
– Contents with default ???)
– Variable names lower
addresses
Variable
names x 5 0x7FFF3110

y ??? 0x7FFF3114

0x7FFF3118
higher
addresses
When variables contain addresses
of other variables, it is helpful to
draw an arrow (pointer) 7
Memory diagrams: global variables
§ Not crucial for global variables (stored in data segment)
– Every variable has a unique label to identify it
– This label is used to access its contents (lw/sw)
// global variables start of
data
n = 42 segment
global i = 0
variable fl = 0.3 lower
names addresses

uniquely n 42 0x10000000
map to
an i 0 0x10000004
address
fl 0.3 0x10000008

higher
addresses 8
Memory diagrams: local variables
§ Why do local variables not have a label?
– That is, why not store local variables in the data segment?
§ Think about the properties of the data segment
– Accessible from all parts of the program
– All labels must be different – they are unique
– Each location can hold only one discrete value Actually, within
a “block”, which
§ Think about the properties of local variables might be a loop,
if-then-else, etc
– Accessible only within a method/function
– May have several vars with same name (different scopes)
• A global and a local, or even several locals within a function
(the latter is not possible in Python or JS; it is in C, Java…)
– May have more than one version of the same function’s
variables (due to recursion)
§ So: data segment not suited for local variables
§ But then, where will we store them?
9
Properties of local variables
§ Must be created/allocated at function entry
§ Must be destroyed/deallocated at function exit
§ Other functions may be called in between, with the
same rules

def a(): def b(): def c():


# create a_var # create b_var # create c_var
a_var = 0 b_var = 0 c_var = 0

b() c() ...


# delete a_var # delete b_var # delete c_var

10
It is a stack!
§ A data type that follows
LIFO: Last In First Out
§ Adding an element: push
– The element is added at
the top of the stack
§ Deleting an element: pop
– The element is popped
from the top of the stack
§ An element can only be
accessed if it is at the top
of the stack

11
Properties of local variables (cont)
§ Allocation/deallocation of local variables obeys LIFO
– The last allocated is the first to be deallocated
§ A stack data structure is ideal for storing them
– Allocate a variable by pushing it on the stack
– Deallocate a variable by popping it off the stack
§ Also helpful for storing other function related info
§ Thus, most computers provide a memory stack for
programs to use:
– Called system stack or runtime stack or process stack
– Initialized by operating system
– User programs push/pop the system stack as needed
– The instruction set provides operations for doing this
12
System stack in MIPS
§ Has its own segment of memory
reserved for OS
– Stack segment: to address
0x7FFFFFFF (0x80000000 is OS) text segment
§ Register $sp (stack pointer) data segment
indicates the top of stack
– Contains the address of the word (heap)
of memory at the top of stack (i.e.,
with lowest address) stack segment
– Its value changes during the
execution of a function reserved for the
Operating System (OS)
§ How do we push and pop
variables?

13
System stack
lower
addresses
This is free
space for the
stack to grow 0x7FFFB308
into
0x7FFFB30C

0x7FFFB310
$sp 0x7FFFB310
0x7FFFB314

All of these 0x7FFFB318


words are part of
the stack 0x7FFFB31C

higher
addresses

14
System stack: pushing
lower
addresses
To push
another word
(this one) onto 0x7FFFB308
the stack ...
0x7FFFB30C

0x7FFFB310
$sp 0x7FFFB310
0x7FFFB314

0x7FFFB318
Subtract 4
from $sp ...
0x7FFFB31C

higher
addresses

15
System stack: pushing
lower
addresses
To push
another word
(this one) onto 0x7FFFB308
the stack ...
0x7FFFB30C

0x7FFFB310
$sp 0x7FFFB30C
0x7FFFB314

0x7FFFB318
Subtract 4
from $sp ...
0x7FFFB31C

Then store higher


a value here addresses

16
System stack: popping
To pop a word lower
(this one) off addresses
the stack ...
0x7FFFB308

... fetch this word 0x7FFFB30C


into a register ...
0x7FFFB310
$sp 0x7FFFB30C
0x7FFFB314

0x7FFFB318
... then add
4 to $sp 0x7FFFB31C

higher
addresses

17
System stack: popping
To pop a word lower
(this one) off addresses
the stack ...
0x7FFFB308

... fetch this word 0x7FFFB30C


into a register ...
0x7FFFB310
$sp 0x7FFFB310
0x7FFFB314

0x7FFFB318
... then add
4 to $sp 0x7FFFB31C

higher
addresses

18
How does the system stack work?
§ At the beginning of a function
– Allocate variables by pushing
necessary space onto stack (subtract
n bytes from $sp)
– Initialize space by storing values in
newly allocated space
§ During function $sp i 5
– Use variables using lw/sw j 2.5
§ At the end of the function k
0xFFFFFFFF
$sp
– Deallocate variables by popping
allocated space from stack (add n
bytes to $sp)

Not necessary on exit


from main since
program is ending 19
Example:
def a():
§ Method a() creates a_var $sp c_var
a_var = 0
§ a() calls b()
Method
b() – b() creates b_var info for c()
– b() calls c()
• c() creates c_var $sp b_var
def b():
• c() exits; c_var is deleted
– b() exits; b_var is deleted Method
b_var = 0 info for b()
§ a() exits; a_var is deleted
c() $sp a_var

def c(): Method


info for a()
c_var = 0
... $sp

20
def main():
Example x = 5
y = 10
...
lower
addresses

0x7FFF310C

0x7FFF3110

0x7FFF3114

0x7FFF3118
$sp 0x7FFF3118
0x7FFF311C

higher
At the beginning of function, stack may addresses
already contain data (indicated by $sp)

21
def main():
Example x = 5
y = 10
...
store initial values lower
addresses

assign 0x7FFF310C
allocated
space to 5
variables x 0x7FFF3110

y 10 0x7FFF3114

0x7FFF3118
$sp 0x7FFF3110
0x7FFF311C

higher
allocate space (4 bytes for x + 4 bytes addresses
for y) by subtracting 8 from $sp
22
Memory diagram: local variables
§ How do we use them?
– We need to refer to local variables. But how?

x 5 0x7FFF3110

y 10 0x7FFF3114

Can’t refer to
location via label
because local Can’t refer to location
variable labels are via address because
not static and unique stack may not be same
(only make sense at depth every time
compile-time not
run-time).
23
Memory diagram: local variables
Store y = 10 at address
$sp + 4 (i.e.0x7FFF3114)

Store x = 5 at address
$sp + 0 (i.e.0x7FFF3110)

x 5 0x7FFF3110

y 10 0x7FFF3114

$sp 0x7FFF3110
Can use stack pointer,
since variables are located
relative to top of stack

24
Reminder: addressing modes
This syntax means “use the
address computed by adding
const to the current contents
of $reg” (i.e., $reg + const)

sw $src, const($reg)

$reg may be
const may be any label or any general-
signed number or purpose
expression known at register,
compile time, including 0 including $0

25
Examples of addressing modes
sw $t0, 4($sp) address is ($sp + 4)

sw $t0, -4($fp) address is ($fp – 4)

lw $a0, 0($sp) address is ($sp + 0)


lw $a0, ($sp)

lw $a0, var($zero) address is ($zero +


address of var)
lw $a0, var

26
Frame pointer
§ Can access local variables relative to stack pointer
($sp), but ...
§ Can be problematic when passing arguments to
functions
– Stack pointer moves to accommodate other function info
– Relative locations of local variables change
§ Easier to access local variables relative to saved copy
of stack pointer
– Copy made before subtracting from $sp to allocate local
variables
§ Saved copy stored in register $fp (frame pointer)
– Local variables accessed relative to $fp
28
def main():
Local variables x = 5
y = 10
...
lower
addresses

$sp 0x7FFF3118 0x7FFF310C

0x7FFF3110

0x7FFF3114

0x7FFF3118
$fp 0x7FFF3118 0x7FFF311C

higher
before allocating local addresses
variables, copy $sp to $fp

29
def main():
Local variables x = 5
y = 10
...
lower
addresses

$sp 0x7FFF3110 0x7FFF310C

x 5 0x7FFF3110
now subtract
from $sp as y 10 0x7FFF3114
before
0x7FFF3118
$fp 0x7FFF3118 0x7FFF311C

higher
addresses

30
Local
access y atvariables
address ($fp – 4) = 0x7FFF3114

access x at address
($fp – 8) = 0x7FFF3110
lower
addresses
$sp 0x7FFF3110
x 5 0x7FFF3110

y 10 0x7FFF3114

0x7FFF3118
$fp 0x7FFF3118 higher
addresses

31
g is a global variable
// A global variable and is stored in data
g = 123 segment, not on stack
def main():
// Three local variables
a = -5
b = 0
c = 230 a –5 ß $sp

// Do some arithmetic b 0
b = g + a
// Do some more arithmetic
c 230
print(c - a)
ß $fp

This memory diagram


corresponds to this
program point
32
.data
a is at -12($fp) # g is global, allocate
# in data segment
b is at -8($fp) g: .word 123

c is at -4($fp) .text
main: # Copy $sp into $fp.
addi $fp, $sp, 0

# Allocate 12 bytes of
a –5 ß $sp # local variables.
addi $sp, $sp, -12

b 0 # Initalize local

230
# variables.
c
addi $t0, $0, -5 # a
ß $fp sw $t0, -12($fp)

sw $0, -8($fp) # b

addi $t0, $0, 230 # c


sw $t0, -4($fp)

# ... rest of program


# follows next slide ...
33
When compiling to MIPS I want you to…
§ Draw memory diagrams for local variables
– Since they are referred to without names in MIPS
– Therefore, remembering their address is vital
§ Be “faithful”:
– Translate each line of code independently of the others (i.e., without
reusing the value of registers computed in previous instructions)
– More lines, but less mistakes…
§ Comment appropriately:
– Each block corresponds to (possibly part of) a line of Python code
– Often each line (not for syscalls, but yes for most other blocks)

34
a is at -12($fp)
b is at -8($fp) .data
c is at -4($fp) # g is global, allocate
# in data segment
g: .word 123

// A global variable .text


g = 123 main: # Copy $sp into $fp.
addi $fp, $sp, 0
def main():
# Allocate 12 bytes of
// Three local variables # local variables.
addi $sp, $sp, -12
a = -5
b = 0 # Initalize local
# variables.
c = 230 addi $t0, $0, -5 # a
sw $t0, -12($fp)
// Do some arithmetic
b = g + a sw $0, -8($fp) # b
// Do some more arithmetic
print(c - a) addi $t0, $0, 230 # c
sw $t0, -4($fp)
# ... rest of program
# follows next slide ...
35
a is at -12($fp) Faithful translation: registers for g and
a are not reused, they are re-loaded
b is at -8($fp)
c is at -4($fp) # ... here is the rest
# of the MIPS code ...
# b = g + a.
lw $t0, g # g
// A global variable lw $t1, -12($fp) # a
g = 123 add $t0, $t0, $t1 # g+a
sw $t0, -8($fp) # store in b
def main(): # print(c-a)
addi $v0, $0, 1 # Print int
// Three local variables lw $t0, -4($fp) # c
a = -5 lw $t1, -12($fp) # a
b = 0 sub $a0, $t0, $t1 # c-a
c = 230 syscall # Do print.
# Now exit.
// Do some arithmetic addi $v0, $0, 10 # Exit.
b = g + a syscall

// Do some more arithmetic


print(c - a) # If this function was not main
# it would need to deallocate
# local variables with:
# addi $sp, $sp, 12

Error: in Python print() adds a new line. We forgot to do this 36


(leftover from Java), so you do not have to do it either
Recap: Global vs Local variables
§ Names of global variables appear in assembly code:
lw $t0, g
§ Names of local variables do not
§ Instead, they are accessed with negative offset from
frame pointer:
lw $t0, -4($fp)
– Offset will be positive for function parameters (later)

§ Thus, it is important to:


– Comment code
– Draw stack memory diagram to know correct addresses

37
Warning: using b as a variable name
§ We have been using a and b as variable names
§ But b is also the name of a MIPS pseudoinstruction
§ This should not cause problems (MIPS instruction
format is very rigid, and prevents this)
§ But MARS seems to have problems in some machines
§ So, from now on we will use other names

IMPORTANT: in your interview prac


Task 1 please use x and y, rather
than a and b, respectively. I will
update my test harness.

38
// A global variable x is at -8($fp)
n = 4
y is at -4($fp)
def main():
// Two local variables

x = 14
y = 0
// Do some arithmetic
y = (n * x) - 7 x 14 ß $sp
// Do some more arithmetic
y = y / 16 y 0
// Do even more arithmetic ß $fp
print(y + n)

39
.data
# allocate global n in data segment
// A global variable n: .word 4
n = 4 .text
main:# Copy $sp into $fp.
def main(): addi $fp, $sp, 0
// Two local variables # Allocate local variables
addi $sp, $sp, -8
x = 14
y = 0 # Initalize local variables
addi $t0, $0, 14 # x
// Do some arithmetic sw $t0, -8($fp)
y = (n * x) - 7 sw $0, -4($fp) # y

// Do some more arithmetic # y = (n*x)-7.


y = y // 16 lw $t0, n # n
lw $t1, -8($fp) # x
// Do even more arithmetic mult $t0, $t1 # n*x
print(y + n) mflo $t0
addi $t0, $t0, -7 # (n*x)-7
sw $t0, -4($fp) # y=(n*x)-7
# ... rest of program
# follows next slide ...
x is at -8($fp)
40
y is at -4($fp)
# ... here is the rest
# of the MIPS code ...
// A global variable
n = 4 # y = y/16
lw $t0, -4($fp) #y
def main(): sra $t0, $t0, 4 #y//16
sw $t0, -4($fp) #y = y//16
// Two local variables
x = 14 # print(y+n)
y = 0 addi $v0, $0, 1 # Print int
lw $t0, -4($fp) # y
// Do some arithmetic lw $t1, n # n
y = (n * x) - 7 add $a0, $t0, $t1 # y+n
syscall # Do print.
// Do some more arithmetic
y = y // 16 # Now exit.
addi $v0, $0, 10 # Exit.
// Do even more arithmetic syscall
print(y + n)

# If this function was not main


# it would need to deallocate
# local variables with:
# addi $sp, $sp, 8

x is at -8($fp)
41
y is at -4($fp)
Summary
§ Memory diagrams
§ System stack
– Pushing and popping
– $sp and $fp
§ Local variables
– Stored on stack
– Accessed with negative offset from $fp
§ Recap of addressing modes
– Register + constant

42

Вам также может понравиться