title: Stack-based virtual machine function call/return implementation issues
body: <p>Today I decided to create a little <strong>stack-based virtual machine in C++11</strong> for fun - everything was going pretty well until I got to function calling and returning from functions.</p>
  
  <p>I've been trying to follow calling guidelines similar to <strong>x86 assembly</strong> but I'm getting really confused.</p>
  
  <p>I have trouble dealing with <em>stack base pointer offsets</em> and with <em>return values</em>.</p>
  
  <p>It seems very hard to keep track of registers used for return values and of arguments (for the function calls) on the stack.</p>
  
  <p>I've created a simple assembly-like language and compiler. Here's a commented example (that my virtual machine compiles and executes). I tried to explain what's happening and to share my thoughts in the comments.</p>
  
  <pre><code>//!ssvasm
  
  $require_registers(3);
  
  // C++ style preprocessor define directives to refer to registers
  $define(R0, 0);
  $define(R1, 1);
  $define(R2, 2); 
  
  // Load the 2.f float constant value into register R0
  loadFloatCVToR(R0, 2.f);
  
  // I want to pass 2.f as an argument to my next function call:
  // I have to push it on top of the stack (as with x86 assembly)
  pushRVToS(R0);
  
  // I call the FN_QUAD function here: calling a function pushes both
  // the current `stack base offset` and the `return instruction index`
  // on the stack
  callPI(FN_QUAD); 
  
  // And get rid of the now-useless argument that still lies on top of the stack
  // by dumping it into the unused R2 register 
  popSVToR(R2);
  
  halt(); // Halt virtual machine execution
  
  
  
  $label(FN_DUP); // Function FN_DUP - returns its argument, duplicated
  
  // I need the arg, but since it's beneath `old offset` and `return instruction`
  // it has to copied into a register - I choose R0 - ...
  
  // To avoid losing other data in R0, I "save" it by pushing it on the stack
  // (Is this the correct way of saving a register's contents?)
  pushRVToS(R0);
  
  // To put the arg in R0, I need to copy the value under the top two stack values
  // (Read as: "move stack value offset by 2 from base to R0")
  // (Is this how I should deal with arguments? Or is there a better way?)
  moveSBOVToR(R0, 2);
  
  // Function logic: I duplicate the value by pushing it twice and adding
  pushRVToS(R0); pushRVToS(R0); addFloat2SVs();
  
  // The result is on top of the stack - I store it in R1, to get it from the caller
  // (Is this how I should deal with return values? Or is there a better way?)
  popSVToR(R1);
  
  popSVToR(R0); // Restore R0 with its old value (it's now at the top of the stack)
  
  // Return to the caller: this pops twice - it uses `old stack base offset` and
  // unconditionally jumps to `return instruction index`
  returnPI();
  
  
  
  $label(FN_QUAD); // Function FN_QUAD
  
  pushRVToS(R0);
  moveSBOVToR(R0, 2);
  
  // Call duplicate twice (using the first call's return value as the second
  // call's argument)
  pushRVToS(R0); callPI(FN_DUP); popSVToR(R2);
  pushRVToS(R1); callPI(FN_DUP); popSVToR(R2);
  
  popSVToR(R0);
  returnPI();
  </code></pre>
  
  <p>I've never programmed in assembly before, so I'm not too sure the techniques I'm using are correct (or efficient).</p>
  
  <p><strong>Is the way I'm handling arguments/return values/registers correct?</strong></p>
  
  <p><strong>Should the caller of a function push the arguments, then call, then pop the arguments?</strong> It seems that using a register would be easier, but I've read that x86 uses the stack to pass arguments. I'm confident that the method I'm using here is incorrect.</p>
  
  <p><strong>Should I push both <code>old stack offset</code> and <code>return instruction index</code> on a function call? Or should I store the <code>old stack offset</code> in a register? (Or avoid storing it at all?)</strong></p>