.data
.text
main:
# 5 parameters
li $s0, 2
li $s1, 3
li $s2, 5
li $s3, 10
li $s4, 20
addi $sp, $sp, -20 # 5 Words are 5 * 4 bytes
sw $s0, 0($sp)
sw $s1, 4($sp)
sw $s2, 8($sp)
sw $s3, 16($sp)
sw $s4, 20($sp)
jal addFiveNumbers
# free stack
addi $sp, $sp, 20
# print the result in $v0
move $a0, $v0
li $v0, 1
syscall
# terminate program
li $v0, 10
syscall
addFiveNumbers:
lw $t0, 0($sp)
lw $t1, 4($sp)
lw $t2, 8($sp)
lw $t3, 16($sp)
lw $t4, 20($sp)
add $v0, $t0, $t1
add $v0, $v0, $t2
add $v0, $v0, $t3
add $v0, $v0, $t4
jr $ra
I took this program from here.
Suppose, I want to add, say, 10 values.
Since there are only eight $s registers, how can I pass 10 arguments?
First of all, the code in your question is passing args on the stack, not following the usual C calling convention, and isn't touching any of the $s
registers, so I don't understand why you think that's relevant at all. How you use the args inside the callee is obviously limited by the number of available registers in the machine, but that's separate from how you pass them.
The normal MIPS calling convention passes args in $a0..$a3
. a
stands for argument. The $s
registers are call-preserved and not usually used for arg-passing.
The standard C calling convention on MIPS, like on all normal ISAs, passes args on the stack for args that don't fit in registers. (Either because it's a big struct by value, or because there are already 4 register args.)
Look at C compiler output on https://godbolt.org/ for MIPS GCC for a function that passes or receives 10 args to see where it looks for them. (Maybe store each arg to a volatile int sink
, so you can compile with optimization and still see it do something.)
You obviously can make up any custom calling convention you want if you're writing to the caller and callee yourself in asm. If I wanted to pass more than 4 register args, I think the natural choice might be to use $t0..$t9
and/or $v0..$v1
after filling up $a0..$a3
.
But sure, if I wanted to pass some read-only args that the caller won't clobber, $s
registers would be appropriate for those. I'm not aware of any C calling conventions for any ISA that have any call-preserved arg-passing registers, but it makes perfect sense in asm.
At that point you're using it with only one caller but maybe from multiple call-sites in the same function, and probably choosing registers based on what's convenient for that caller. So it's barely an independent function. But that's fine.