Every unoptimised function I disassemble starts with push rbp, mov rbp, rsp, sub rsp, 32 and ends with leave and ret. Locals are then addressed as [rbp-4], [rbp-8] and so on. With -O2 the first two instructions disappear and everything is addressed from rsp instead.
What exactly do RSP and RBP point to at each step, where is the return address, and why is the frame pointer optional? I would like to be able to draw the stack for a given function.




