ITSC 2181 - Module 6 Unit 4/5 Functions in RISC-V

Functions in RISC-V Introduction

  • RISC-V Architecture: Involves using functions to improve code readability and efficiency.

  • Creates functions to handle repetitive tasks, making code modular.

Programming Constructs:

  • Example C Code - Simple Conditional:

  if (a != b) 
      i = a - b;
  else 
      i = 0;
  • RISC-V Assembly Equivalent:

  lw x1, 0(x11)        # load a
  lw x2, 0(x12)        # load b
  beq x1, x2, else     # branch if a == b
  sub x5, x1, x2       # x5 = a - b
  sw x5, 0(x15)        # store result in i
  beq x0, x0, exit     # unconditionally jump to exit
  else:
  sw x0, 0(x15)       # store 0 in i
  exit:

Function Definition in Assembly

  • Calling Functions:

    • Arguments must be passed through registers.

    • Control transfer instructions (e.g., jal) to jump to function code block (branching).

    • Allocate storage for function execution and manage return values.

    • Perform function operations.

    • Store function result in a register.

    • Return to instruction after control transfer (exit function code block).

  • 3 Main Things Needed:

    1. Assembly instructions

      • Control transfer needed to go back and forth between calling function and function that is being called

    2. Data storage

      • Arguments and return values from functions must be stored somehow in registers and/or memory

    3. Stack memory to manage data allocation

  • Callee vs. Caller Functions:

    • Caller: Starts execution of a function (e.g., main() in C).

    • Callee: Performs operations for the caller (print a statement, compute a value, etc), using temporary registers (t registers).

Stack Management in RISC-V

  • 4 Parts of Memory Layout Components:

    • Text: Code Section, where instructions are stored.

    • Static Data: Global variables.

    • Dynamic Data: Heap for dynamic memory (e.g., malloc() in C).

    • Stack: Automatic storage for a function; used for function local variables and return addresses, follows Last-In-First-Out (LIFO) principle.

Register Usage in Functions

  • Important Registers:

    • x0/zero: Always 0.

    • ra: Return address register for storing address to return to after function call.

    • sp: Stack pointer, points to the current stack location.

    • s0-s11: Saved registers for persistent values across function calls.

    • t0-t6: Temporary registers for intermediate values.

    • a0-a7: Argument registers for passing function arguments and return values.

Jump Instructions for Function Calls

  • j: Unconditional jump to a specific address.

  • jal: Jump and link; saves return address in ra.

    • Tells computer to go to label code block and store first instruction after the jumping to the label in the given register

    • Used for making function calls

  • jr: Jump register; jumps to address specified by a register.

  • jalr: Jump and link register; a combination of jal and jr to return control to caller.

    • Saves address of next instruction in the register, adds immediate value offset to the given source register

    • E.g., jal x1, label stores the return address in x1 and jumps to label.

  • Examples:

  jal x1, label      # jump to label without saving return address
  jalr x1, 0(source register) # jump to the address in source register without saving return

Example of Function Call in C to Assembly

  • C Function Example:

int loop() {
    int sum = 0;
    for(int n = 10; n > 0; n--){
        sum += n;
    }
    return sum;
}
  • Assembly Conversion:

addi s1, x0, 0     # Initialize sum
loop:
beq s0, x0, exit  # exit loop if n = 0
add s1, s1, s0     # sum += n
addi s0, s0, -1    # decrement n
jal x0, loop       # repeat loop
exit:

Register Name(s)

Usage

x0/zero

Always holds 0

ra

Holds the return address

sp

Holds the address of the boundary of the stack

t0-t6

Holds temporary values that do not persist after functional calls

s0-s11

Holds values that persist after function calls

a0-a1

Holds the first two arguments to the function or the return values

a2-a7

Holds any remaining arguments

Lab Implementation Notes

  • Learning objectives include implementing loops and function calls in RISC-V assembly language.

  • Example projects could include integer accumulation and averaging of arrays.

  • Use environment calls (ecall) for outputting values and program termination.

Key Takeaways:

  • Proper use of the stack and appropriate register management is crucial in assembly programming.

  • Understanding function calls, local scope, and stack operations are foundational for advanced programming in assembly languages.