0% found this document useful (0 votes)
249 views

CS61C Homework 3 - C To MIPS Practice Problems: Problem 1 - Useful Snippets

This homework assignment provides practice problems for translating C code to MIPS assembly code. It includes three problems: 1) Translating different C constructs like while loops, for loops, and do-while loops to preserve the original loop structure in MIPS when printing a string. 2) Converting a recursive Fibonacci function in C to MIPS recursively without optimization. 3) Modifying the recursive Fibonacci function to memoize results by checking a memoization table before recursively computing values. The document provides the C code for each problem and the corresponding MIPS assembly code solutions. It aims to familiarize students with the process of translating C to MIPS through examples of different loop constructs and recursive functions

Uploaded by

Elisa Tsan
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
249 views

CS61C Homework 3 - C To MIPS Practice Problems: Problem 1 - Useful Snippets

This homework assignment provides practice problems for translating C code to MIPS assembly code. It includes three problems: 1) Translating different C constructs like while loops, for loops, and do-while loops to preserve the original loop structure in MIPS when printing a string. 2) Converting a recursive Fibonacci function in C to MIPS recursively without optimization. 3) Modifying the recursive Fibonacci function to memoize results by checking a memoization table before recursively computing values. The document provides the C code for each problem and the corresponding MIPS assembly code solutions. It aims to familiarize students with the process of translating C to MIPS through examples of different loop constructs and recursive functions

Uploaded by

Elisa Tsan
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 8

CS61C Homework 3 - C to MIPS Practice Problems

TA: Sagar Karandikar

Spring 2015

This homework is an ungraded assignment designed to familiarize you with translating C code to MIPS.
We will release solutions on Sunday, Feb 22nd, so that you may use them to study for the exam.

Problem 1 - Useful Snippets


In this section, we’ll take the same problem (that of printing a string) and approach it using different C
constructs. This should allow you to see how various C constructs are translated into MIPS.
Suppose that we have a print function, but that this function only takes one character and prints it to
the screen. It expects the character to be in the lower 8 bits of $a0.

A) Translate into MIPS, while preserving the while loop structure:

void string_print(char *print_me) {


while (*print_me != ’\0’) {
print(*print_me);
print_me++;
}
}

Solution:

stringprint :
# p r o l o g u e , backup ra , backup s 0
addiu $sp , $sp , −8
sw $ra , 0 ( $sp )
sw $s0 , 4 ( $sp )

addiu $s0 , $a0 , 0 # copy a0 t o s 0 s o we don ’ t have t o back i t up


l b u $a0 , 0 ( $ s 0 ) # l o a d c h a r a c t e r f o r f i r s t i t e r a t i o n

Loop :
beq $a0 , $0 , Ret # break out o f l o o p i f l o a d e d c h a r a c t e r i s n u l l t e r m i n a t o r
j a l p r i n t # c a l l p r i n t ( t h i s i s why we l o a d e d t o a0 )

1
addiu $s0 , $s0 , 1 # i n c r e m e n t p o i n t e r
l b u $a0 , 0 ( $ s 0 ) # l o a d next c h a r a c t e r
j Loop

Ret :
# e p i l o g u e , r e s t o r e ra , r e s t o r e s 0
lw $s0 , 4 ( $sp )
lw $ra , 0 ( $sp )
addiu $sp , $sp , 8
j r $ra

B) Translate into MIPS, while preserving the for loop structure (your function is given the string length):

void string_print(char *print_me, int slen) {


for (int i = 0; i < slen; i++) {
print(*(print_me+i));
}
}

Solution:

stringprint :
# p r o l o g u e , backup ra , backup s0 , s1 , s 2
addiu $sp , $sp , −16
sw $ra , 0 ( $sp )
sw $s0 , 4 ( $sp )
sw $s1 , 8 ( $sp )
sw $s2 , 1 2 ( $sp )

addiu $s0 , $a0 , 0 # copy a0 t o s 0 s o we don ’ t have t o back i t up


addiu $s1 , $a1 , 0 # copy a1 t o s 1 s o we don ’ t have t o back i t up
addiu $s2 , $0 , 0 # i n i t i a l i z e l o o p c o u n t e r

Loop :
beq $s2 , $s1 , Ret # break out o f l o o p i f i == s l e n
addu $a0 , $s2 , $ s 0
l b u $a0 , 0 ( $a0 ) # g e t f i r s t c h a r
j a l p r i n t # c a l l p r i n t ( t h i s i s why we l o a d e d t o a0 )
addiu $s2 , $s2 , 1 # i n c r e m e n t l o o p var
j Loop

Ret :

2
# e p i l o g u e , r e s t o r e ra , r e s t o r e s0 , s1 , s 2
lw $s2 , 1 2 ( $sp )
lw $s1 , 8 ( $sp )
lw $s0 , 4 ( $sp )
lw $ra , 0 ( $sp )
addiu $sp , $sp , 16
j r $ra

C) Translate into MIPS, while preserving the do while loop structure:

void string_print(char *print_me) {


if (!(*print_me)) {
return;
}
do {
print(*print_me);
print_me++;
} while (*print_me);
}

Solution:

stringprint :
# p r o l o g u e , backup ra , backup s 0
addiu $sp , $sp , −8
sw $ra , 0 ( $sp )
sw $s0 , 4 ( $sp )

addiu $s0 , $a0 , 0 # copy a0 t o s 0 s o we don ’ t have t o back i t up


l b u $a0 , 0 ( $ s 0 ) # l o a d c h a r a c t e r f o r f i r s t i t e r a t i o n
beq $a0 , $0 , Ret # do n o t h i n g i f l o a d e d c h a r a c t e r i s n u l l t e r m i n a t o r

Loop :
j a l p r i n t # c a l l p r i n t ( t h i s i s why we l o a d e d t o a0 )
addiu $s0 , $s0 , 1 # i n c r e m e n t p o i n t e r
l b u $a0 , 0 ( $ s 0 ) # l o a d next c h a r a c t e r
bne $a0 , $0 , Loop # c o n t i n u e l o o p i f l o a d e d c h a r a c t e r i s not n u l l t e r m i n a t o r

Ret :
# e p i l o g u e , r e s t o r e ra , r e s t o r e s 0
lw $s0 , 4 ( $sp )
lw $ra , 0 ( $sp )
addiu $sp , $sp , 8

3
j r $ra

Problem 2 - Recursive Fibonacci


Convert the following recursive implementation of Fibonacci to MIPS. Do not convert it to an iterative
solution.

int fib(int n) {
if (n == 0) {
return 0;
} else if (n == 1) {
return 1;
}
return fib(n-1) + fib(n-2);
}

Solution:

# n o t e : t h i s s o l u t i o n i s i n s t r u c t i o n a l and not n e c e s s a r i l y o p t i m i z e d

fib :
addiu $sp , $sp , −12
sw $ra , 0 ( $sp ) #backup r a f o r r e c u r s i v e c a l l s
sw $a0 , 4 ( $sp ) #backup a0 f o r r e c u r s i v e c a l l s
sw $s0 , 8 ( $sp ) #backup s 0 s i n c e we u s e i t

beq $a0 , $0 , ReturnZero


addiu $t0 , $0 , 0
s l t i $t0 , $a0 , 2 # you can a l s o beq with one
bne $t0 , $0 , ReturnOne

addiu $a0 , $a0 , −1


jal fib
move $s0 , $v0
lw $a0 , 4 ( $sp )
addiu $a0 , $a0 , −2
jal fib
add $v0 , $v0 , $ s 0

lw $s0 , 8 ( $sp )
lw $ra , 0 ( $sp )
addiu $sp , $sp , 12

4
j r $ra

ReturnZero :
# e p i l o g u e j u s t t o make our r e t u r n s c o n s i s t e n t
lw $s0 , 8 ( $sp )
lw $ra , 0 ( $sp )
addiu $sp , $sp , 12
l i $v0 , 0
j r $ra

ReturnOne :
# e p i l o g u e j u s t t o make our r e t u r n s c o n s i s t e n t
lw $s0 , 8 ( $sp )
lw $ra , 0 ( $sp )
addiu $sp , $sp , 12
l i $v0 , 1
j r $ra

Problem 3 - Memoized Fibonacci


Now, modify your recursive Fibonacci implementation to memoize results. For the sake of simplicity, you
can assume that the array given to you (memolist) is at least n elements long for any n. Additionally, the
array is initialized to all zeros.

int fib(int n, int* memolist) {


if (n == 0) {
return 0;
} else if (n == 1) {
return 1;
}
if (memolist[n]) {
return memolist[n];
}
memolist[n] = fib(n-1, memolist) + fib(n-2, memolist);
return memolist[n];
}

Solution:

# n o t e : t h i s s o l u t i o n i s i n s t r u c t i o n a l and not n e c e s s a r i l y o p t i m i z e d

fib :

5
addiu $sp , $sp , −12
sw $ra , 0 ( $sp ) #backup r a f o r r e c u r s i v e c a l l s
sw $a0 , 4 ( $sp ) #backup a0 f o r r e c u r s i v e c a l l s
sw $s0 , 8 ( $sp ) #backup s 0 s i n c e we u s e i t

beq $a0 , $0 , ReturnZero


addiu $t0 , $0 , 0
s l t i $t0 , $a0 , 2 # you can a l s o beq with one
bne $t0 , $0 , ReturnOne

# not t h e n = 1 o r n = 0 c a s e s , check memoized t a b l e


s l l $t0 , $a0 , 2 # c o n v e r t n t o o f f s e t ( i n t s a r e 4 b y t e s )
addiu $t0 , $t0 , $a1 # add o f f s e t t o b a s e p o i n t e r ( $a1 )
lw $v0 , 0 ( $ t 0 )
bne $v0 , $0 , RetMemo

# not i n t a b l e , compute i t t h e old−f a s h i o n e d way


addiu $a0 , $a0 , −1
jal fib
move $s0 , $v0
lw $a0 , 4 ( $sp )
addiu $a0 , $a0 , −2
jal fib
add $v0 , $v0 , $ s 0

# s t o r e copy i n t h e memoize t a b l e
lw $a0 , 4 ( $sp ) # f i r s t , r e s t o r e a0
s l l $t0 , $a0 , 2 # c o n v e r t n t o o f f s e t ( i n t s a r e 4 b y t e s )
addiu $t0 , $t0 , $a1 # add o f f s e t t o b a s e p o i n t e r ( $a1 )
sw $v0 , 0 ( $ t 0 )

# epilogue
lw $s0 , 8 ( $sp )
lw $ra , 0 ( $sp )
addiu $sp , $sp , 12
j r $ra

ReturnZero :
# e p i l o g u e j u s t t o make our r e t u r n s c o n s i s t e n t
lw $s0 , 8 ( $sp )
lw $ra , 0 ( $sp )

6
addiu $sp , $sp , 12
l i $v0 , 0
j r $ra

ReturnOne :
# e p i l o g u e j u s t t o make our r e t u r n s c o n s i s t e n t
lw $s0 , 8 ( $sp )
lw $ra , 0 ( $sp )
addiu $sp , $sp , 12
l i $v0 , 1
j r $ra

RetMemo : # r e t u r n s v a l u e a l r e a d y i n v0
# epilogue
lw $s0 , 8 ( $sp )
lw $ra , 0 ( $ s 0 )
addiu $sp , $sp , 12
j r $ra

Problem 4 - Self-Modifying MIPS


Write a MIPS function that performs identically to this code when called many times in a row, but does not
store the static variable in the static segment (or even the heap or stack):

short nextshort() {
static short a = 0;
return a++;
}

Tips/Hints:

• You can assume that the short type is 16 bits wide. shorts represent signed numbers.

• You can assume that your MIPS code is allowed to modify any part of memory.

• See the title of this question.

Solution:

nextshort :
addiu $v0 , $0 , 0
l a $t0 , n e x t s h o r t
lw $t1 , 0 ( $ t 0 )
addiu $t3 , $0 , 0xFFFF

7
and $t2 , $t1 , $ t 3
beq $t2 , $t3 , H a n d l e S p e c i a l
addiu $t1 , $t1 , 1
sw $t1 , 0 ( $ t 0 ) # s t o r e i n c r e m e n t e d i n s t r u c t i o n
j r $ r a # r e t v a l u e i s a l r e a d y i n v0
H a n d l e S p e c i a l : # here , h a n d l e t h e o v e r f l o w c a s e
l a $t6 , b a c k u p i n s t
lw $t1 , 0 ( $ t 6 )
sw $t1 , 0 ( $ t 0 )
j r $ r a # r e t v a l u e i s a l r e a d y i n v0

backupinst :
addiu $v0 , $0 , 0

You might also like