MIPS - Fibonacci Series: Main and fib function

In summary, the code provided includes a MIPS program that calculates and prints the first N elements of the Fibonacci sequence using a function called fib(N, &array). The value N is passed in $a0 and the address of the array is passed in register $a1. The code also includes a main program that prompts the user for input and calls the fib function to print the results. However, there may be issues with transferring the function to a separate file, and it is unclear which MIPS interpreter is being used. More specific information is needed to determine the cause of the program not working.
  • #1
Margarita0076
5
0
Homework Statement
MIPS - Fibonacci Series.
Relevant Equations
Write and test the fib function in two linked files (Fib.asm, fib_main.asm).
Write and test the fib function in two linked files (Fib.asm, fib_main.asm). Your solution must be made up of a function called fib(N, &array) to store the first N elements of the Fibonacci sequence into an array in memory. The value N is passed in $a0, and the address of the array is passed in register $a1. The first few numbers of the Fibonacci sequence are 1, 1, 2, 3, 5, 8, 13 …
Your solution must also include an assembly 'main' program that accepts an integer from the user less than or equal to 45. Call the fib function and print the results. Prompt the user for the input. It can be assumed that the input value is <= 45.
Required Input: An unsigned 32-bit integer up to 45.
Required Output: Your output should look something like the following example.

How many elements of the Fibonacci series? 20
1
1
2
3
5
8
13
21
34
55
89
144
233
377
610
987
1597
2584
4181
6765

I wrote this code in MIPS, but when I create function separate my code is not work. What is wrong in my code? Thank you.
Code:
# MAIN METHOD
.data
prompt1: .asciiz "Enter the sequence length "
prompt2: .asciiz "The Fibonacci value is: "
array: .space 180
newline: .asciiz " "

.text
.globl main
# Print prompt1
main:
la $a1,array
li $t0,0
li $t1,1
sw $t1,($a1)
loop:
li $v0, 4
la $a0, prompt1
syscall
# Read integer
li $v0, 5
syscall
move $a0,$v0

jal fib

bgt $a0,45,loop
move $s1,$a0
move $s2,$a0
subi $s1,$s1,1
# Print prompt2
li $v0, 4
la $a0, prompt2
syscall

# FIB FUNCTION
.text
.globl fib

fib:
beqz $s1,print
move $t2,$t1
add $t1,$t1,$t0
move $t0,$t2
addi $a1,$a1,4
sw $t1,($a1)
subi $s1,$s1,1
j fib
print:
la $a1,array
loop1:
beqz $s2,exit
li $v0, 1
lw $a0, ($a1)
syscall
la $a0,newline #for newline
li $v0,4
syscall

addi $a1,$a1,4
subi $s2,$s2,1
j loop1

jr $ra
 
Last edited by a moderator:
Physics news on Phys.org
  • #2
Margarita0076 said:
Homework Statement:: MIPS - Fibonacci Series.
Relevant Equations:: Write and test the fib function in two linked files (Fib.asm, fib_main.asm).

Write and test the fib function in two linked files (Fib.asm, fib_main.asm). Your solution must be made up of a function called fib(N, &array) to store the first N elements of the Fibonacci sequence into an array in memory. The value N is passed in $a0, and the address of the array is passed in register $a1. The first few numbers of the Fibonacci sequence are 1, 1, 2, 3, 5, 8, 13 …
Your solution must also include an assembly 'main' program that accepts an integer from the user less than or equal to 45. Call the fib function and print the results. Prompt the user for the input. It can be assumed that the input value is <= 45.
Required Input: An unsigned 32-bit integer up to 45.
Required Output: Your output should look something like the following example.

How many elements of the Fibonacci series? 20
1
1
2
3
5
8
13
21
34
55
89
144
233
377
610
987
1597
2584
4181
6765

I wrote this code in MIPS, but when I create function separate my code is not work. What is wrong in my code? Thank you.
Code:
# MAIN METHOD
.data
prompt1: .asciiz "Enter the sequence length "
prompt2: .asciiz "The Fibonacci value is: "
array: .space 180
newline: .asciiz " "

.text
.globl main
# Print prompt1
main:
la $a1,array
li $t0,0
li $t1,1
sw $t1,($a1)
loop:
li $v0, 4
la $a0, prompt1
syscall
# Read integer
li $v0, 5
syscall
move $a0,$v0

jal fib

bgt $a0,45,loop
move $s1,$a0
move $s2,$a0
subi $s1,$s1,1
# Print prompt2
li $v0, 4
la $a0, prompt2
syscall

# FIB FUNCTION
.text
.globl fib

fib:
beqz $s1,print
move $t2,$t1
add $t1,$t1,$t0
move $t0,$t2
addi $a1,$a1,4
sw $t1,($a1)
subi $s1,$s1,1
j fib
print:
la $a1,array
loop1:
beqz $s2,exit
li $v0, 1
lw $a0, ($a1)
syscall
la $a0,newline #for newline
li $v0,4
syscall

addi $a1,$a1,4
subi $s2,$s2,1
j loop1

jr $ra
Which MIPS interpreter are you using? I'm familiar with both MARS and QtSPIM. As I recall, they work a little differently if your program consists of more than 1 file. For example, in MARS, IIRC, the two files should be in one directory, and when you assemble the code, you do it for all files in the given directory. In the code that you posted, is this one file or did you paste the two of them together?

Also, when you say it "doesn't work," you need to be more specific.
 
  • #3
I use Mars interpreter. There are two files here. I think that I can not correctly transfer the function to a separate file. With such a transfer of code, my program simply does not start.

-------1 file-------
# MAIN METHOD
.data
prompt1: .asciiz "Enter the sequence length "
prompt2: .asciiz "The Fibonacci value is: "
array: .space 180
newline: .asciiz " "

.text
.globl main
# Print prompt1
main:
la $a1,array
li $t0,0
li $t1,1
sw $t1,($a1)
loop:
li $v0, 4
la $a0, prompt1
syscall
# Read integer
li $v0, 5
syscall
move $a0,$v0

jal fib

bgt $a0,45,loop
move $s1,$a0
move $s2,$a0
subi $s1,$s1,1
# Print prompt2
li $v0, 4
la $a0, prompt2
syscall-------2 file-------
# FIB FUNCTION
.text
.globl fib

fib:
beqz $s1,print
move $t2,$t1
add $t1,$t1,$t0
move $t0,$t2
addi $a1,$a1,4
sw $t1,($a1)
subi $s1,$s1,1
j fib
print:
la $a1,array
loop1:
beqz $s2,exit
li $v0, 1
lw $a0, ($a1)
syscall
la $a0,newline #for newline
li $v0,4
syscall

addi $a1,$a1,4
subi $s2,$s2,1
j loop1

jr $ra
 
  • #4
Margarita0076 said:
I think that I can not correctly transfer the function to a separate file. With such a transfer of code, my program simply does not start.
It is possible to do it, though. A major problem with your code is that you are using array as if it were a global variable, instead of passing its address either on the stack or in the registers that are usually used for passing parameters to functions -- $a0, $a1, $a2, and $a3 for integers and $f0, and others for floating point numbers.

This code works with floating point numbers, which you might not have been exposed to yet, but I'm hopeful you can pick up on how I'm passing values to the routine in the other file.

Here is an example program for the MARS interpreter with the code in two files.
The first file contains the main entry point.
Code:
# DistanceMain.s  
# Given a pair of points in the plane, calculate the distance between them.
# The Distance routine is in a separate file, DistanceFn.s, and both files are in
# their own directory. To build in MARS, set "Assemble all files in directory" in Settings,
# and open file with main in the Editor.
# 
# Note: FP registers are $f0, $f1, etc.
 
        .globl  main
.eqv PRINT_FLT 2
.eqv PRINT_STR 4
.eqv TERMINATE 10
        
        .data
P1x:    .float 1.0
P1y:    .float 2.0
P2x:    .float 4.0
P2y:    .float 6.0

SummaryStr:    .asciiz "Distance is: "

        .text
main:    

    addu $sp, $sp, -16        # Pass all parameters to Distance routine on the stack
    l.s $f12, P1x            # Load x coord of first point
    s.s $f12, ($sp)
    l.s $f12, P1y            # Load y coord of first point
    s.s $f12, 4($sp)
    l.s $f12, P2x            # Load x coord of second point
    s.s $f12, 8($sp) 
    l.s $f12, P2y            # Load Y coord of second point
    s.s $f12, 12($sp) 

    jal Distance
    addu $sp, $sp, 16        # clean up stack

    la $a0, SummaryStr        # Display a summary string
    li $v0, PRINT_STR        
    syscall

    mov.s $f12, $f0            # copy Distance return value to $f12 prior to displaying it
    li $v0, PRINT_FLT        # print the distance
    syscall

    li $v0, 10                #terminate
    syscall

Here's the file with the function in it.
Code:
# Distance procedure - return the distance between points (x1, y1) and (x2, y2)
# float Distance(float x1, float y1, float x2, float y2) - prototype
# arguments on stack:
# 
#   x1 - $sp
#   y1 - $sp + 4
#   x2 - $sp + 8
#   y2 - $sp + 12
# returns the distance sqrt((x2 - x1)^2 + (y2 - y1)^2)^.5 in $f0 
    .globl Distance
Distance:
    l.s $f12, 8($sp)        # get x2 from stack
    l.s $f14, ($sp)            # get x1 from stack
    sub.s $f16, $f12, $f14        # $f16 = x2 - x1
    mul.s $f16, $f16, $f16        # $f16 = $f16 * $f16

    l.s $f12, 12($sp)        # get y2 from stack
    l.s $f14, 4($sp)        # get y1 from stack
    sub.s $f18, $f12, $f14        # $f18 = y2 - y1
    mul.s $f18, $f18, $f18        # $f18 = $f18 * $f18
    add.s $f16, $f18, $f16        # $f16 = (x2 - x1)^2 + (y2 - y1)^2
    
    sqrt.s $f0, $f16          
    jr $ra
 
  • Like
Likes Margarita0076
  • #5
Here's maybe a more understandable example, also in MARS form. Below is the file that contains the main function. Inside main there is a call to RowSum, a function in another file.

Code:
# array_rowsums.s 
# This program calculates the sum of the elements of a row of an M x N matrix.

# Constants
.eqv NUM_ROWS  5
.eqv NUM_COLS  6
.eqv ELT_SIZE  4    

.eqv PRINT_INT  1
.eqv PRINT_STR  4
.eqv READ_INT   5
.eqv TERMINATE  10

        .data
Input_str:    .asciiz "Enter the row number: "
Summary_str:    .asciiz "Sum of elements in that row: "

#        .align 2    # Align the array on a 4-byte boundary
        
array1:
row0:        .word   1,  6,  8, 10, 12, 2
row1:        .word  14,  2, 18, 20, 24, 3
row2:        .word  30, 32,  3, 10,  5, 4
row3:        .word   1,  2,  3,  4,  5, 5
row4:        .word  10, 15, 20,  5,  6, 6

rowAddresses:    .word row0, row1, row2, row3, row4    

    .text
main:
    # Prompt user for the row number
    la $a0, Input_str
    jal PrintMsg
    
    li $v0, READ_INT
    syscall            # Row number is in $v0
    
    # Todo: check that 0 <= row number < NUM_ROWS
 
    la $a0, rowAddresses    # Load the address of the array that contains row addresses
    li $t0, ELT_SIZE    # Size in bytes of each address in rowAddresses
    mul $t0, $t0, $v0    # Convert the row number into a byte offset
    add $a0, $a0, $t0    # $a0 now set to address of i-th row    
    li $a1, NUM_COLS    
    jal RowSum        # return value is in $v0

    move $a2, $v0        # temporarily store $v0 for later use

    # Print summary string
    la $a0, Summary_str    
    jal PrintMsg

    # Print returned row sum
    move $a0, $a2
    li $v0, PRINT_INT
    syscall
    
    li $v0, TERMINATE      # Exit program
         syscall
.end main

# PrintMsg - displays a string
# Parameters:
#   Address of string to print in $a0
# Returns nothing
PrintMsg:
    
    li $v0, PRINT_STR
    syscall
    jr $ra
.end PrintMsg                 # Produces a warning in MARS, but will still run

Here's the code in the separate file. For this to work, the code has to have a .globl directive that exports the name of the function so that the other file knows about it.
The comments provide all the needed information about the registers used for parameter passing and the return value.
Code:
# RowSum - Calculates the sum of the elements in a specified row of a matrix
# Prototype: int RowSum(int * rowAddress, int count);
# Parameters:
#   rowAddress - address of the first element of the i-th row in an array, passed in $a0
#   count - no. of elements in a row, passed in $a1
# Returns the sum of the elements of the specified row in $v0
# Local vars used:
#   $t0 - loop counter
#   $t1 - row sum
#   $t2 - address of the current element in the i-th row
#   $t3 - temp storage of an array element
    .globl RowSum        # Export the name of this routine so that the main program can use it.
RowSum:
    move $t0, $0        # loop counter
    move $t1, $0        # initialize row sum
    lw $t2, ($a0)    

Loop:    
    bge $t0, $a1, Done
    lw $t3, ($t2)
    add $t1, $t1, $t3    # sum = sum + $t3
    addi $t2, $t2, ELT_SIZE    # increment address to next element in row
    addi $t0, $t0, 1    # increment loop counter
    b Loop    

Done:
    move $v0, $t1        # pass sum back to main
    jr $ra            # return to main
.end RowSum
 

FAQ: MIPS - Fibonacci Series: Main and fib function

What is the Fibonacci series?

The Fibonacci series is a mathematical sequence where each number is the sum of the two preceding numbers, starting with 0 and 1. So the first few numbers in the series are 0, 1, 1, 2, 3, 5, 8, 13, 21, etc.

What is MIPS?

MIPS (Microprocessor without Interlocked Pipeline Stages) is a reduced instruction set computer (RISC) architecture used in many modern processors. It is commonly used in embedded systems and is known for its simplicity and efficiency.

What is the main function in MIPS?

The main function in MIPS is the starting point of a program. It is where the program execution begins and it typically contains instructions for initializing variables, calling other functions, and performing other necessary tasks.

What is the fib function in MIPS?

The fib function in MIPS is a function that calculates the Fibonacci series. It takes in a parameter (usually the desired index of the series) and returns the corresponding number in the series.

How is the Fibonacci series calculated in MIPS?

The Fibonacci series can be calculated in MIPS using a recursive algorithm, where the fib function calls itself to calculate the preceding numbers in the series. The base case for this function is when the parameter is 0 or 1, in which case the function simply returns the parameter itself. Otherwise, it recursively calls itself with the parameter decreased by 1 and 2, and adds the results to get the Fibonacci number at that index.

Similar threads

Replies
2
Views
4K
Replies
1
Views
2K
Replies
1
Views
7K
Replies
4
Views
9K
Replies
1
Views
5K
Replies
4
Views
21K
Replies
12
Views
11K
Back
Top