Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
lab 4
  • Loading branch information
Jerry Shi committed Feb 9, 2024
1 parent ce725ce commit 37b33f1
Show file tree
Hide file tree
Showing 2 changed files with 184 additions and 0 deletions.
130 changes: 130 additions & 0 deletions lab4/lab4.md
@@ -0,0 +1,130 @@
# Binary search

**Firm Deadline:** Monday, 2/19/2024

**Important:** This is a firm deadline. Lab4-test is due on the same day.

Write concise comments in code.

## Learning Objectives

* Review RISC-V ISA, e.g., support for control flow and memory access

* Implement nested functions and recursion

* Save/restore registers in a function

## Description

In this lab, we write function `binary_search` in RISC-V. The prototype of the
function and an implementation in C is at the end of this page. Translate the
C code at the bottom of the page to RISC-V assembly code.

The skeleton code is in `lab4.s`. Function `binary_search` is located at the
end of the file. It is empty in the skeleton code.

There are some constraints/tips.

1. To ensure we do not use pseudoinstructions, we turn off the feature in
RARs. In Settings, uncheck "Permit extended (pseudo) instructions and
formats".

2. Follow the C code closely. Although binary search is simple, it is very
easy to make mistakes if you have not written it many times.

3. We keep variable `left` in register `s1`. Other local variables do not have
to be in a saved register. Think about why we need to keep `left`, but not
other variables, in a saved register.

4. There should be only one exit (one return instruction) in the function. In
the C code, we use `goto f_exit` on purpose. With one exit, we do not have
multiple copies of clean up code, e.g., restoring saved registers.

5. There is an IF-ELSEIF-ELSE structure. Write the outline first, without
instructions in each branch. Follow the order of branches in C code: IF
branch, then the ELSEIF branch, and finally the ELSE branch. It is easier
to check the code this way.

6. There is only one LW instruction, for reading `a[half]`, between the code
that saves/restores registers.

7. During the execution of the program, examine how `ra` and `sp` registers
are changed and what have been saved on the stack. It helps to understand
how funciton and local storage work.

### Testing

The array used for testing has multiple of 10s between 0 and 990, inclusive.
Here are some inputs/outputs of the binary search function. Note the program
does not print anything to the terminal. We check the return value in RARS in
the Registers tab.

```
0
0
460
46
990
99
45
-1
1000
-1
-3
-1
```

## Deliverables

Please submit lab4.s and take lab4-test in HuskyCT by the deadline.

In addition to the output, the auto grader also checks some values in registers
and in memory. For example, the value of `s1` should be preserved through the
function all.

## C code

Here is the C code of the function.

``` C
int binary_search(int a[], int n, int v)
{
int rv;

if (n == 0) { // nothing in the array
rv = -1;
goto f_exit; // return -1
}

int half = n / 2; // integer division
int half_v = a[half];

if (half_v == v) {
rv = half;
}
else if (v < half_v) {
// search the first half, excluding a[half]
rv = binary_search(a, half, v);
}
else { // v > half_v
// search the second half, excluding a[half]
int left = half + 1;

// &a[left] means the address of a[left]
rv = binary_search(&a[left], n - left, v);

if (rv >= 0) {
rv += left;
}
}

f_exit:
return rv;
}

```
54 changes: 54 additions & 0 deletions lab4/lab4.s
@@ -0,0 +1,54 @@
# CSE 3666 Lab 4
# TAG: 5fd71ac11b8a14746aa31ed0caf142197fb20839

.data
.align 2
word_array: .word
0, 10, 20, 30, 40, 50, 60, 70, 80, 90,
100, 110, 120, 130, 140, 150, 160, 170, 180, 190,
200, 210, 220, 230, 240, 250, 260, 270, 280, 290,
300, 310, 320, 330, 340, 350, 360, 370, 380, 390,
400, 410, 420, 430, 440, 450, 460, 470, 480, 490,
500, 510, 520, 530, 540, 550, 560, 570, 580, 590,
600, 610, 620, 630, 640, 650, 660, 670, 680, 690,
700, 710, 720, 730, 740, 750, 760, 770, 780, 790,
800, 810, 820, 830, 840, 850, 860, 870, 880, 890,
900, 910, 920, 930, 940, 950, 960, 970, 980, 990

# code
.text
.globl main
main:
addi s0, x0, -1
addi s4, x0, -1
addi s5, x0, -1
addi s6, x0, -1
addi s7, x0, -1

# help to check if any saved registers are changed during the function call
# could add more...

# la s1, word_array
lui s1, 0x10010 # starting addr of word_array in standard memory config
addi s2, x0, 100 # 100 elements in the array

# read an integer from the console
addi a7, x0, 5
ecall

addi s3, a0, 0 # keep a copy of v in s3

# call binary search
addi a0, s1, 0
addi a1, s2, 0
addi a2, s3, 0
jal ra, binary_search

exit: addi a7, x0, 10
ecall

#### Do not change lines above
binary_search:

# TODO

0 comments on commit 37b33f1

Please sign in to comment.