# A subroutine with its arguments in registers

[Courses](https://asm-editor.specy.app/learn/courses.md) › [RISC-V assembly](https://asm-editor.specy.app/learn/courses/risc-v.md) › Examples

Web page: https://asm-editor.specy.app/learn/courses/risc-v/examples/subroutine-with-register-arguments

> Pass arguments in a0 and a1, return a result in a0, align the stack pointer, and follow the caller-saved register rules in a leaf subroutine.

The same program in: [M68K](https://asm-editor.specy.app/learn/courses/m68k/examples/subroutine-with-register-arguments.md), [MIPS](https://asm-editor.specy.app/learn/courses/mips/examples/subroutine-with-register-arguments.md), [Z80](https://asm-editor.specy.app/learn/courses/z80/examples/subroutine-with-register-arguments.md), [x86-64](https://asm-editor.specy.app/learn/courses/x86/examples/subroutine-with-register-arguments.md)

The greatest common divisor of two numbers can be found with Euclid's method: replace the pair with
the second number and the remainder of the division, then repeat until the second number is zero.
Here that calculation is a subroutine. Its first argument arrives in `a0`, its second in `a1`, and
its result comes back in `a0`.

```riscv
.text
.globl main

# gcd(a, b): a arrives in a0 and b in a1; the result leaves in a0.
gcd:
    beqz a1, gcd_done   # while (b != 0)
    rem t0, a0, a1     # t = a % b
    mv a0, a1          # a = b
    mv a1, t0          # b = t
    j gcd
gcd_done:
    ret

main:
    li a0, 84
    li a1, 36
    addi sp, sp, -12    # 0x7fffeffc becomes 0x7fffeff0, divisible by 16
    jal gcd
    addi sp, sp, 12     # restore the Playground's initial sp
    mv s0, a0           # keep the result: 12
```

The Playground starts `sp` at `0x7fffeffc`. RISC-V requires it to be a multiple of 16 at a call, so
`main` subtracts 12 before `jal` and adds 12 back immediately after the return. `gcd` does not need
stack space of its own, but it still begins with an aligned `sp`.

The loop uses the argument registers to hold intermediate values. For `gcd(84, 36)`, `a0` finishes as 12 and
`a1` finishes as 0. The caller copies the result from `a0` to `s0` before using `a0` for anything
else.

The calling convention is the agreed set of rules that lets caller and subroutine understand each
other. The `a` and `t` registers are caller-saved: a call may change them, so a caller that needs an
old value must save it before calling. That is why `gcd` may use `t0` without restoring it. The `s`
registers are callee-saved: a subroutine that changes one must restore its old value before `ret`.
This `gcd` does not change any `s` register.

`jal gcd` writes `0x00400028`, the address of the following `addi`, into `ra`. `ret` jumps to the
address in `ra`, so execution resumes there and restores `sp`. `gcd` is a **leaf subroutine**: it
does not call another subroutine, so nothing overwrites its incoming `ra` and it need not save it.
If it contained another `jal`, it would have to preserve that return address, normally in an aligned
stack frame.

## Your turn: absolute difference

Write the leaf subroutine `difference`. It receives two nonnegative signed 32-bit integers (0 through
2,147,483,647) in `a0` and `a1` and returns their absolute difference in `a0`. It may change `a1`
and any `t` register, but it must not change an `s` register. Do not use memory or call another
subroutine. `main` puts the value 12345 in `s3` so the test can check that the subroutine leaves it unchanged.

Also replace each `addi sp, sp, 0` around a call: subtract 12 before `jal` so `sp` is 16-byte aligned,
then add 12 after the return. The three calls check both argument orders and equal arguments. At the
end, `sp` must be back at its initial value.

*Exercise: the code to start from, checked by the testcase after it:*

```riscv
.text
.globl main

difference:
    # Return |a0 - a1| in a0.
    ret

main:
    li s3, 12345        # callee-saved sentinel: difference must leave this unchanged

    li a0, 20
    li a1, 13
    addi sp, sp, 0      # replace 0 with the adjustment before the call
    jal difference
    addi sp, sp, 0      # replace 0 with the adjustment after the call
    mv s0, a0

    li a0, 4
    li a1, 11
    addi sp, sp, 0
    jal difference
    addi sp, sp, 0
    mv s1, a0

    li a0, 9
    li a1, 9
    addi sp, sp, 0
    jal difference
    addi sp, sp, 0
    mv s2, a0
```

*Testcase for the program above (JSON):*

```json
{
    "expectedRegisters": {
        "s0": 7,
        "s1": 7,
        "s2": 0,
        "s3": 12345,
        "sp": "0x7fffeffc"
    }
}
```

<details>
<summary>Show solution</summary>

*Solution:*

```riscv
.text
.globl main

difference:
    blt a0, a1, second_is_larger
    sub a0, a0, a1
    ret
second_is_larger:
    sub a0, a1, a0
    ret

main:
    li s3, 12345

    li a0, 20
    li a1, 13
    addi sp, sp, -12
    jal difference
    addi sp, sp, 12
    mv s0, a0

    li a0, 4
    li a1, 11
    addi sp, sp, -12
    jal difference
    addi sp, sp, 12
    mv s1, a0

    li a0, 9
    li a1, 9
    addi sp, sp, -12
    jal difference
    addi sp, sp, 12
    mv s2, a0
```

</details>

## Instructions in this Lecture

- RISC-V: [`beqz`](https://asm-editor.specy.app/documentation/risc-v/instruction/beqz.md), [`rem`](https://asm-editor.specy.app/documentation/risc-v/instruction/rem.md), [`mv`](https://asm-editor.specy.app/documentation/risc-v/instruction/mv.md), [`j`](https://asm-editor.specy.app/documentation/risc-v/instruction/j.md), [`ret`](https://asm-editor.specy.app/documentation/risc-v/instruction/ret.md), [`li`](https://asm-editor.specy.app/documentation/risc-v/instruction/li.md), [`addi`](https://asm-editor.specy.app/documentation/risc-v/instruction/addi.md), [`jal`](https://asm-editor.specy.app/documentation/risc-v/instruction/jal.md), [`blt`](https://asm-editor.specy.app/documentation/risc-v/instruction/blt.md), [`sub`](https://asm-editor.specy.app/documentation/risc-v/instruction/sub.md)

Previous: [Even or odd, count the set bits, multiply by shifting](https://asm-editor.specy.app/learn/courses/risc-v/examples/bit-tricks.md)

Next: [Stack arguments and a stack frame](https://asm-editor.specy.app/learn/courses/risc-v/examples/subroutine-with-stack-arguments.md)
