Thursday, 1 October 2015 Exam one week from today (See Web site for - - PowerPoint PPT Presentation
Thursday, 1 October 2015 Exam one week from today (See Web site for - - PowerPoint PPT Presentation
Thursday, 1 October 2015 Exam one week from today (See Web site for review exercises) Next Tuesday: review for exam Today: Short intro to pointers in C Values vs. addresses; lw vs. la More on functions in MIPS: the stack Keep reading P&H
Pointers in C
Sample C program:
#include <stdio.h> int main() { int i = 20; int *j = &i; *j = 30; printf(“Value of i = %d\n”,i); } OUTPUT: $ gcc pt.c $ ./a.out Value of i = 30 Why??
Pointers in C
#include <stdio.h> int main() { int i = 20; int *j = &i; *j = 30; printf(“Value of i = %d\n”,i); } This means that j is a pointer variable (more specifically, a “pointer to an int”) This means “address of variable i” This means “put 30 into address pointed at by j”
Pointers in MIPS
.data .align 2 i: .word 20 j: .space 4 .text la $t0,i sw $t0,j li $t0,30 lw $t1,j sw $t0,0($t1)
Load the ADDRESS of i Load the CONSTANT 30 Load the CONTENTS of j Offset/base notation (p. 69)
Pointers in MIPS
The example on the previous slide is saved as program “pointers.asm” in the “oct1” folder of the shared repository.
Back to Functions
We introduced pointers so that we could explain the behavior of functions in C. Problem: write a function with two int arguments, a and b. The function’s job is to swap the values of a and b. Here’s the obvious (and wrong) solution:
Back to Functions
void swap(int a, int b) { int temp = a; a = b; b = temp; }
It doesn’t work! If you try this: int i = 10; int j = 20; swap(i,j); printf(“%d %d\n”, i,j); you get “10 20” for output.
Back to Functions
void swap(int a, int b) { int temp = a; a = b; b = temp; } ... int i = 10,j = 20; swap(i,j);
10 20 20 10 10 a: b: i: j: temp: The swap is performed on a COPY! Memory: C uses “pass by value” in function calls
Back to Functions
void swap(int * i, int * j) { int temp = *i; *i = *j; *j = temp; } ... int i = 10, j = 20; swap(&i, &j);
Use pointers to integers, rather than integers Send the addresses of i and j, rather than their values (See program “swap.asm” in oct1 folder
- f shared repository)
Now...let’s write “swap” in MIPS!
Desired behavior: ... a: .space 4 (or .word ...value...) b: .space 4 (or .word ...value...) ... la $a0,a # first argument reg. la $a1,b # second argument reg. jal swap # contents of locations a, b are now swapped
“Swap” in MIPS! Desired Behavior
... a: .space 4 b: .space 4 ... la $a0,a la $a1,b jal swap Compare to C: swap(&a, &b); Load address (“la”) rather than “lw”
Before We Go On...
A few words about “register conventions.” In a MIPS program, you can use (almost) any register you want in a calculation–$t0, $t1, …, $a0, $a1, …, $v0, $v1, $s0, $s1, … . BUT there are certain agreed-upon conventions that MIPS programmers use, both to make programs easier to understand and to prevent errors.
See Figure 2.14, page 105 in P&H
Register Conventions
The “a”-registers: argument registers When calling a function, use the $a0, $a1, $a2, and $a3 registers to hold (up to 4) arguments to the function. (If you have more than 4 arguments, use other registers, but always start with the “a” registers….). NOTE: when we make syscalls for printing an int or printing a string, we must put things in $a0.
Page 105 in P&H
Register Conventions
The “s”-registers: saved-value registers When using registers to hold important program values that will be needed at multiple places in the program (data values, loop indices, and
- ther things you might declare in a C program),
use $s0, $s1, …, $s7. So, for instance, a payroll program might have variables like “hrs_worked”, “pay_rate”, etc. These might be saved in s-registers.
Page 105 in P&H
Register Conventions
The “v”-registers: return-value registers Functions that return values should place the return value in register $v0. (Register $v1 is also sometimes needed to return values, but usually only $v0 is required.) NOTE: for syscalls, $v0 is also used to identify which syscall operation is being used: print_int or print_str or read_int or …).
Page 105 in P&H
Register Conventions
The “t”-registers: temporary registers Any value that is needed only “for a moment,” like an intermediate result of a complicated calculation or a place to store the result of a “slt” comparison test, can go into one of the t-
- registers. Unlike s-registers, t-registers are
assumed to hold values that don’t need to be saved beyond their brief, momentary use.
Page 105 in P&H
Doing a Swap in MIPS
Assume that the addresses of a and b, the locations to be swapped are already loaded into $a0 and $a0. Here’s the swap:
lw $t0,0($a0) # Load contents of a into t0 lw $t1,0($a1) # Load contents of b into t1 sw $t0,0($a1) # swap: copy t0 into b sw $t1,0($a0) # swap: copy t1 into a
Offset/base notation (p. 69)
Doing a Swap in MIPS
Here’s our first approximation to a function in MIPS that does a swap–we just add “jr $ra”:
swap: lw $t0,0($a0) # Load contents of a into t0 lw $t1,0($a1) # Load contents of b into t1 sw $t0,0($a1) # swap: copy t0 into b sw $t1,0($a0) # swap: copy t1 into a jr $ra # return to calling program
A “Safer” Version of Swap
Suppose we aren’t very good at respecting the register conventions and we’re worried that registers $t0 and $t1 might contain important values that we don’t want to lose. Or suppose we are writing the swap function for some other programmer who may not follow the register conventions and who needs the values in $t0 and $t1 to be preserved. We want to play it safe and “back up” the values of $t0 and $t1.
The Stack
Special area in memory for holding temporary values. The stack grows “down” from higher memory locations to lower ones.
How to Use the Stack (pp. 96-104)
The stack operations of “push” and “pop” are achieved by changing the value of the register $sp (the “stack pointer” register). This contains an address in memory (see previous slide). To push a certain number of bytes, we reduce the value of $sp by that number, then fill in the values of the new bytes.
How to Use the Stack (pp. 96-104)
Example:
addi $sp,$sp,-8 # grow stack by 8 bytes sw $t0,0($sp) # put something on stack sw $t1,4($sp) # put something on stack
stack stuff 3456012 3456011 3456010 3456009 3456008 3456007 3456006 3456005 3456004 3456003 $sp = 3456012 $sp = 3456004 0($sp) $sp = 3456008 4($sp) stack stuff 3456012 3456011 3456010 3456009 3456008 3456007 3456006 3456005 3456004 3456003 contents
- f
register t1 contents
- f
register t0 addi $sp,$sp,-8
How to Use the Stack (pp. 96-104)
To pop a certain number of bytes off the stack, we just copy those bytes somewhere else and then add that number of bytes to $sp.
stack stuff 3456012 3456011 3456010 3456009 3456008 3456007 3456006 3456005 3456004 3456003 contents
- f
register t1 contents
- f
register t0
lw $t0,0($sp) lw $t1,4($sp) addi $sp,$sp,8
stack stuff 3456012 3456011 3456010 3456009 3456008 3456007 3456006 3456005 3456004 3456003 $sp = 3456004 0($sp) $sp = 3456012
How to Use the Stack (pp. 96-104)
The function should do all the work. So … if we want to perform swap, but preserve registers $t0 and $t1 so we don’t accidentally overwrite important information, we must: ■ grow the stack ■ back up values of $t0, $t1 onto stack ■ use $t0, $t1 in our function ■ restore values from stack back into $t0, $t1 ■ shrink the stack ■ return
Swap Function in MIPS
swap: addi $sp,$sp,-8 # Reserve space on stack sw $t0,0($sp) # Save current value of t0 on stack sw $t1,4($sp) # Save current value of t1 on stack lw $t0,0($a0) # Load first value into t0 lw $t1,0($a1) # Load second value into t1 sw $t0,0($a1) # swap: copy t0 into second address sw $t1,0($a0) # swap: copy t1 into first address lw $t0,0($sp) # Restore old t0 from stack lw $t1,4($sp) # Restore old t1 from stack addi $sp,$sp,8 # Shrink stack to original size jr $ra # return
Refer back to previous slides!!