Skip to content

CS 631-02 Systems Foundations — Meeting Summary

  • Date: Mar 05, 2026, 2:48 PM Pacific Time (US and Canada)
  • Meeting ID: 882 2309 0019
  • Topic: Function calls and calling conventions in assembly (including recursion)

Quick Recap

The session focused on: - Mechanics of function calls, stack management, and handling caller-saved vs. callee-saved registers - Passing more than eight arguments via the stack and via callee-saved registers - Recursion, demonstrated with a factorial function in Rust and assembly - Using GDB to visualize nested stack frames, return addresses, and unwinding - Upcoming lab and a new project involving string manipulation in assembly and RISC-V code generation for a mini-compiler

Next Steps

  • Greg: Release a new, lighter-weight Debian QEMU image for class use once built
  • Greg: Push an updated version of the in-class example code with the corrected register restoration order
  • Greg: Release the next lab ASAP, including content not previously available in CS 315
  • Greg: Release the next project next week (earlier than usual), covering string handling and RISC-V code generation

Detailed Summary

Autograder Timeout and Image Updates

  • The autograder had a hard-coded 30-second build timeout in both Python and Rust runners, causing Rust builds to time out on the Beagle.
  • The Rust timeout was fixed; the latest release was posted on Campus Wire.
  • Work is underway on a lighter Debian image for QEMU that boots faster than the current Ubuntu image.
  • The lecture transitioned into function calls and calling conventions in assembly.

Understanding Function Call Mechanics

  • Function calls were framed as fundamental across languages and platforms.
  • Key registers:
  • Program Counter (PC) implicitly updates as instructions execute.
  • Return Address (RA) holds the address to return to after a call.
  • On a function call, PC is set to the callee’s address, and RA is set to PC + 4, enabling a correct return to the caller.

Assembly Call and Return Instructions

  • The return address (RA) should be preserved on the stack to ensure correct returns.
  • The call instruction updates RA; the callee frequently saves RA in its prologue and restores it in the epilogue if it will be clobbered.
  • Instruction mapping:
  • “call” is a pseudo-instruction for JAL
  • “ret/return” is a pseudo-instruction for JALR
  • Slide corrections included adding a needed addi in the example sequence.

Caller-Saved and Callee-Saved Registers

  • Roles change dynamically: a function can be both a caller and a callee.
  • Rules of thumb:
  • Caller-saved: The caller saves any volatile registers it needs after the call (e.g., a registers, temporaries).
  • Callee-saved: The callee preserves registers designated as non-volatile (e.g., saved registers) across the call.
  • Passing arguments:
  • First eight arguments use the a0a7 registers.
  • Additional arguments are passed on the stack.
  • Terminology emphasized: prologue, epilogue, stack frame.
  • An example addition function illustrated strict adherence to calling conventions.

Assembly Language Stack Management

  • Demonstrated how to allocate stack space, preserve registers, and orchestrate multi-function calculations.
  • Emphasized planning ahead in assembly due to the lack of high-level abstractions that automate bookkeeping.
  • The next lab will require more complex stack management and disciplined use of calling conventions.

Lecture Plans and Sort Function

  • Upcoming content: handling more than eight arguments and recursion.
  • A different approach from Phil’s sort example will be presented.
  • A prior assignment (expression evaluator in assembly) was briefly referenced.

Function Call Register Management

  • Two approaches:
  • Caller-saved: Caller pushes volatile state before calling; restores after return.
  • Callee-saved: Callee saves non-volatile registers it uses; restores before returning.
  • Compilers mix strategies for performance.
  • For more than eight arguments, extra values are placed on the stack and accessed by the callee.

C Compiler Function Argument Optimization

  • In optimized builds, the compiler:
  • Uses registers for the first eight arguments
  • Loads the ninth and beyond from the stack
  • Unoptimized builds may show explicit stack allocation for locals; optimized builds prefer registers.
  • This behavior aligns with the RISC-V calling convention, where the caller allocates stack space and the callee retrieves stack-passed arguments.

Recursion in Assembly Language

  • Recursion was illustrated with a factorial example.
  • Key points:
  • Each recursive call creates a new stack frame.
  • Registers (including RA) must be preserved; local data is stored in the frame.
  • Recursion is simply repeated function calls with appropriate state management.
  • Rust syntax for recursion was contrasted with its assembly implementation.

Recursive Function and Assembly Walkthrough

  • A step-by-step walkthrough showed:
  • Stack frame creation and teardown across recursive calls
  • RA preservation and updates
  • Unwinding behavior and how return values propagate
  • Announcements:
  • A new lab will be released soon with fresh challenges
  • Next week’s project includes string manipulation in assembly and RISC-V code generation for a mini-compiler

Key Terms

  • PC (Program Counter), RA (Return Address)
  • Caller-saved vs. callee-saved registers
  • Prologue, epilogue, stack frame
  • JAL, JALR, addi
  • a0a7 argument registers
  • RISC-V calling convention