0% found this document useful (0 votes)
276 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
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
276 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
We take content rights seriously. If you suspect this is your content, claim it here.
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