6.828 Lecture 5 - Calling conventions & stack frames
- Notes: https://pdos.csail.mit.edu/6.828/2021/lec/l-riscv.txt
- Slides: https://pdos.csail.mit.edu/6.828/2021/lec/l-riscv-slides.pdf
- Video: https://www.youtube.com/watch?v=s-Z5t_yTyTM&feature=youtu.be
- Prep: https://pdos.csail.mit.edu/6.828/2021/readings/riscv-calling.pdf
Lecture Notes
printf
in the kernel doesn’t involve any syscalls; it’s implemented specially for the kernel inkernel/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
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.