# Calling Convention - damn_simple_architecture

## Keyboard shortcuts

Press `←` or `→` to navigate between chapters

Press `S` or `/` to search in the book

Press `?` to show this help

Press `Esc` to hide this help

# Calling Convention

Step | Responsibility | Action | Description
--- | --- | --- | ---
0 | Caller | Save Current State | Ensure that any registers with important data in are pushed to the stack so that they can be restored later.
1 | Caller | Push arguments | Push exactly n arguments to the stack (in order, last argument pushed first)
2 | Caller | Call function | Execute `call namespace::function`this automatically pushes the return address (pcx) and jumps to the function
3 | Function | Set up stack frame | Execute `push bpr; mov spr, bpr` to establish new stack frame
4 | Function | Access arguments | Read arguments starting at `spr+8` (first 3 args at offsets 8, 12, 16)
5 | Function | Execute function | Perform the function's operations using the arguments
6 | Function | Store return value | Write return value (if any) to `spr+8`
7 | Function | Restore stack frame | Execute `mov bpr, spr; pop bpr` to restore previous stack frame
8 | Function | Return | Execute `return` pseudo-instruction to return to caller
9 | Caller | Clean up stack | Pop exactly n arguments from the stack to clean up
10 | Caller | Handle unused values | Use `pop zero` to discard any unused stack values if needed
11 | Caller | Restore State | Pop any registers that were pushed in step 0 (or `pop zero` if no longer needed)

Notes:

- The namespace in step 2 is the name assigned in the `include` statement
- The `call` pseudo-instruction automatically handles return address management so long as the callee does not mess with the stack
- Arguments are accessed by the callee using offsets from the base pointer (bpr)

### Function Control

Mnemonic | Operands | Description
--- | --- | ---
CALL | `namespace::function` | Call a function with automatic return address management
RETURN | - | Return from a function to the caller

Examples:

`call-local.dsa`

    // ensure the stack is set up first!

    caller:
        push rg0
        push rg1

        call callee  // make call to a local function
        pop rg0     // put result in rg0
        pop zero    // void second return val

    callee:
        // setup new stack frame
        push bpr
        mov spr, bpr

        // function body

        // restore the stack frame
        mov bpr, spr
        pop bpr
        return              ; Return from the current function

`call-external.dsa`

    include external "./external.dsa"

    // ensure the stack is set up first!
    db string: "Hello, world!"
    caller:
        // push args
        lwi string, rg0
        push rg0
        call external::callee // do something with the string
        pop zero

`external.dsa`

    callee:
        // set up the stack
        push bpr
        mov spr, bpr

        // function body

        // restore the stack frame
        mov bpr, spr
        pop bpr
        return              ; Return from the current function