6.828 Lecture 5 - Calling conventions & stack frames

Lecture Notes

  • printf in the kernel doesn’t involve any syscalls; it’s implemented specially for the kernel in kernel/printf.c
  • *.S → assembly, *.o → binary/object code
  • x86 ISA: 3 full books, 3 new instructions per month on average, not open source
  • ARM ISAs are RISC as well (but not RISC-V)
  • RISC-V ISA is modular, and most modules are optional
  • gdb
    • tui enable, layout <reg|asm|src|split>, focus <layout>
    • info <break|reg|frame|args|locals>
    • backtrace
    • p *argv@argc
    • watch <variable>
  • RISC-V compressed instructions – 16 bits instead of 64 bits
  • Caller saved registers are (expected to be) unchanged when a function returns
  • Callee saved registers are (allowed to be) changed when a function returns
  • Stack frame contents: return address, saved regs, local vars (args?), pointer to the start of the previous frame
  • Stack frames are not necessarily sized the same, the stack pointer (sp) points to the end of the current frame, and the frame pointer (fp) points to the start
  • RISC-V stacks grow downwards, from high addresses to low ones

What is a calling convention, even?

(Moved to Calling Convention)

RISC-V Specification Chapter 18: Calling Convention

400

It looks like values from the ABI Name column are used in RISC-V assembly. What is an “ABI Name” / why is the first column even required?

The RISC-V calling convention passes arguments in registers when possible. Up to eight integer registers, a0–a7, and up to eight floating-point registers, fa0–fa7, are used for this purpose.

If argument i < 8 is a floating-point type, it is passed in floating-point register fa$i$; otherwise, it is passed in integer register a$i$.

However, floating-point arguments that are part of unions or array fields of structures are passed in integer registers.

Is this lossy?

Arguments smaller than a pointer-word are passed in the least-significant bits of argument registers. Correspondingly, sub-pointer-word arguments passed on the stack appear in the lower addresses of a pointer-word, since RISC-V has a little-endian memory system.

Values are returned from functions in integer registers a0 and a1 and floating-point registers fa0 and fa1.

(…) return values that fit into two pointer-words are returned in a0 and a1. Larger return values are passed entirely in memory; the caller allocates this memory region and passes a pointer to it as an implicit first parameter to the callee.

Edit