mvbg

VM_RET_N

VM_RET_N is a GBVM instruction used to return from a near call (a subroutine within the same memory bank) and simultaneously remove a specified number of arguments from the stack.

Purpose: When you use VM_CALL to jump to a subroutine, you often pass arguments to that subroutine by pushing them onto the stack. After the subroutine has completed its task, it needs to return control to the calling script and clean up the arguments it received from the stack. VM_RET_N handles both of these actions:

This instruction is crucial for proper function call conventions and stack management when dealing with subroutines within the same memory bank, ensuring that the stack remains balanced and that arguments are correctly removed after use.

Syntax:

VM_RET_N N

Usage Example: Reusable Function with Arguments

Let’s create a reusable function ADD_VALUES that takes two numbers from the stack, adds them, and leaves the result on the stack. The function itself needs to clean up the two arguments it received.

; In your main script:

; Variables
VAR_NUM1:
  .R_INT16 10
VAR_NUM2:
  .R_INT16 20
VAR_SUM_RESULT:
  .R_INT16 0

; Push arguments for the ADD_VALUES function
VM_PUSH_VALUE VAR_NUM1 ; Stack: [10]
VM_PUSH_VALUE VAR_NUM2 ; Stack: [10, 20]

; Call the ADD_VALUES function
VM_CALL ADD_VALUES

; After ADD_VALUES returns, the sum (30) is on the stack.
; Store the result into VAR_SUM_RESULT
VM_SET_INT16 VAR_SUM_RESULT, 0 ; The 0 is a placeholder, value taken from stack

; ... continue main script ...

; --- Subroutine Definition ---
ADD_VALUES:
  ; At this point, the stack contains: [return_address, VAR_NUM1_value, VAR_NUM2_value]
  ; We need to get the values for addition.

  ; Get the values from the stack (top-most first)
  VM_GET_TLOCAL VAR_TEMP_B, 0 ; Get VAR_NUM2_value (20)
  VM_GET_TLOCAL VAR_TEMP_A, 1 ; Get VAR_NUM1_value (10)

  ; Perform the addition
  VM_RPN
    .R_REF_MEM .R_INT16, VAR_TEMP_A
    .R_REF_MEM .R_INT16, VAR_TEMP_B
    .R_OPERATOR +
    .R_INT16
  VM_STOP

  ; The sum (30) is now on top of the stack.
  ; Return from the call and remove 2 arguments (VAR_NUM1_value, VAR_NUM2_value)
  VM_RET_N 2

In this example, VM_CALL ADD_VALUES pushes the return address and then the arguments. Inside ADD_VALUES, the arguments are retrieved and used in the calculation. Finally, VM_RET_N 2 ensures that when the routine returns, the two arguments (10 and 20) are popped from the stack, leaving only the calculated sum (30) on top, which is then stored by the calling script.

Analogy to other programming languages: This is analogous to a function returning in C/C++ where the calling convention dictates that the callee (the function being called) is responsible for cleaning up the arguments from the stack. For example, in __stdcall calling convention on x86, the RET N instruction (where N is the number of bytes of arguments) handles both returning and stack cleanup. It ensures that the stack is properly unwound after a function call.