## Registers
# | Register | Usage | Type | Description |
# | -------- | --------- | ------- | ------------------------------------------------ |
# | `$a0` | input | integer | year to check |
# | `$v0` | output | boolean | input is leap year (`0` = `false`, `1` = `true`) |
# | `$t0-9` | temporary | any | used for temporary storage |
.globl is_leap_year
is_leap_year:
li $v0, 0
andi $t0, $a0, 3
bnez $t0, end
li $t0, 100
div $a0, $t0
mfhi $t0
bnez $t0, set_leap
mflo $t0
andi $t0, $t0, 3
bnez $t0, end
set_leap:
li $v0, 1
end:
jr $ra
Equivalent C code:
#include <stdlib.h>
int is_leap_year(int year) {
if ((year & 3) != 0) {
return 0;
}
div_t by_100 = div(year, 100);
return by_100.rem != 0 || (by_100.quot & 3) == 0;
}
This approach uses the andi
instruction to determine if the year is divisible by 4
by relying on the fact that if a number is divisible by 4
, its two least significant bits
will be zero.
To determine if the year is divisible by 100
, we then use div
combined with mfhi
to get
the remainder. Finally, if we need to check if the year is divisible by 400
, we use another
trick: calling div
left the quotient of the division by 100
in the lo
register. Thus,
we can fetch that quotient using mflo
and then re-use the same trick as before to determine
if that quotient is divisible by 4
(making the year divisible by 400
).