# Lab 5
Name: G Jaswanth
Roll No.: CS22B020
---
## Question 1
### **Code with loop**
```assembly=
.data
array: .word 1 2 3 4 5 6 7 8 9 10 11 12
str: .string " "
.text
la x1 array
la x30 array
li x2 12
li x3 12
loop:
lw x4 44(x1)
addi x4 x4 3
sw x4 44(x1)
addi x1 x1 -4
addi x2 x2 -1
beq x2 x0 print
j loop
print:
lw x4 0(x30)
add a0 x4 x0
li a7 1
ecall
la a0 str
li a7 4
ecall
addi x30 x30 4
addi x2 x2 1
beq x2 x3 exit
j print
exit:
li a7 10
ecall
```
### Output

### **Code after unrolling by factor 4**
```assembly=
.data
array: .word 1 2 3 4 5 6 7 8 9 10 11 12
str: .string " "
.text
la x1 array
la x3 array
li x2 12
li x8 12
loop:
lw x4 44(x1)
lw x5 40(x1)
lw x6 36(x1)
lw x7 32(x1)
addi x4 x4 3
addi x5 x5 3
addi x6 x6 3
addi x7 x7 3
sw x4 44(x1)
sw x5 40(x1)
sw x6 36(x1)
sw x7 32(x1)
addi x1 x1 -16
addi x8 x8 -4
beq x8 x0 print
j loop
print:
lw x9 0(x3)
add a0 x9 x0
li a7 1
ecall
la a0 str
li a7 4
ecall
addi x3 x3 4
addi x2 x2 -1
bne x2 x0 print
Exit:
li a7 10
ecall
```
### Output

### Observations:
We saw unrolled loop have higher IPC(instructions per cycle) than a normal loop, this may be due to
* Unrolling reduces the overhead of branch instructions and loop control, leading to fewer pipeline stalls
* It increases instruction-level parallelism by allowing multiple instructions from different iterations of the loop to be executed concurrently.
* There's a reduced likelihood of branch mispredictions since there are fewer branches in the unrolled loop.
Therefore, the unrolled loop execution typically yields a higher IPC compared to the normal loop execution.
**console output**
4 5 6 7 8 9 10 11 12 13 14
---
## Question 2
**Code**
```assembly=
.data
str: .string " "
node1: .word 1 # value
.word 0 # pointer to next node
node2: .word 2
.word 0
node3: .word 3
.word 0
node4: .word 4
.word 0
node5: .word 5
.word 0
node6: .word 6
.word 0
node7: .word 7
.word 0
node8: .word 8
.word 0
node9: .word 9
.word 0
node10: .word 10
.word 0
.text
# link the nodes
la x1, node1
la x2, node2
la x3, node3
la x4, node4
la x5, node5
la x6, node6
la x7, node7
la x8, node8
la x9, node9
la x10, node10
sw x2, 4(x1)
sw x3, 4(x2)
sw x4, 4(x3)
sw x5, 4(x4)
sw x6, 4(x5)
sw x7, 4(x6)
sw x8, 4(x7)
sw x9, 4(x8)
sw x10, 4(x9)
sw x0, 4(x10) # Set the last node's next pointer to NULL
# reverse the linked list
la x30, node1 # x30 points to the first node
li x31, 0 # Initialize x31 (previous) to NULL
li x20, 0
li x21, 10 #length of linked list
reverse_loop:
lw x20, 4(x30) # Load the next pointer of the current node
sw x31, 4(x30) # Update the next pointer of the current node to the previous node
mv x31, x30 # Update the previous node to the current node
mv x30, x20 # Move to the next node
bne x20 x0 reverse_loop # Repeat until t0 is not NULL
mv x16 x31
print: #printing the values
lw x18 0(x16)
add a0 x18 x0
li a7 1
ecall
la a0 str
li a7 4
ecall
addi x21 x21 -1
lw x19 4(x16)
mv x16 x19
bne x21 x0 print
# At this point, t1 points to the new head of the reversed list
# You can use t1 or the label of the first node of the reversed list to access it
```
**2 a**
Output:
10 9 8 7 6 5 4 3 2 1
### Observations
Each node in the linked list consists of two main parts:
* Data: This is the actual information or payload stored in the node. It could be a single value or a collection of values.
* Pointer: This is a memory address that points to the next node in the sequence. In RISC-V assembly language, pointers are typically represented using memory addresses stored in registers.
Overall, a linked list in RISC-V assembly language provides a flexible data structure for storing and manipulating data in a non-contiguous manner, allowing for efficient insertion, deletion, and traversal of elements.
---
## Question 3
**Code**
```assembly=
.data
node1: .word 1,0 # the NULL pointer is 0
node2: .word 2,0
node3: .word 3,0
node4: .word 4,0
node5: .word 5,0
node6: .word 6,0
node7: .word 7,0
node8: .word 8,0
node9: .word 9,0
node10: .word 10,0
newNode: .word 11,0
buffer: .string " "
.text
j main
create_node:
la t0 node1
addi t0 t0 4 # curr = word storing address
loop:
lw t1 0(t0)
addi t0 t0 8 # curr = next word storing address
beq t1 x0 endloop
bne t1 x0 loop
endloop:
addi t0 t0 -8
la t2 newNode
sw t2 0(t0)
jalr x0 ra 0
print_node:
li a7, 4 # System call for print string
la a0, buffer # Load the address of the buffer
ecall # Print "Value: "
lw a0, 0(a1) # Load the value of the current node
li a7, 1 # System call number for printing integer
ecall # Print the integer
li a7, 4 # System call for print string
la a0, 10 # Load the address of the newline character
ecall # Print newline
jr ra # Return
main:
# link the nodes
la t0 node1
la t1 node2
sw t1 4(t0)
la t0 node3
sw t0 4(t1)
la t1 node4
sw t1 4(t0)
la t0 node5
sw t0 4(t1)
la t1 node6
sw t1 4(t0)
la t0 node7
sw t0 4(t1)
la t1 node8
sw t1 4(t0)
la t0 node9
sw t0 4(t1)
la t1 node10
sw t1 4(t0)
jal ra create_node
# Print the linked list
la a1, node1 # a1 points to the first node
loop_print:
beqz a1, end_print # If a1 is NULL, end the loop
lw a0, 0(a1) # Load the value of the current node
jal ra, print_node # Print the value of the current node
lw a1, 4(a1) # Move to the next node
j loop_print
end_print:
# End of program
li a7, 10 # System call number for exit
ecall # Exit the program
# Exit the program
```
**3 a**
1 2 3 4 5 6 7 8 9 10 11
**Observation:**
* We linked numbers from
* 1 2 3 4 5 6 7 8 9 10
* and inserted 11 at the end afterwards giving output as
* 1 2 3 4 5 6 7 8 9 10 11
---