The MIPS assembler was originally written by Christian Pirker.
Currently the assembler and disassembler covers most of the MIPS32 architecture and doesn’t support FP instructions.
The register names $a0
–$a3
are not available to avoid
shadowing hex numbers. Use register numbers $4
–$7
instead.
Nothing distinguishes registers from immediate values. Use explicit
opcode names with the i
suffix for instructions with immediate
argument. E.g. addiu,
in place of addu,
.
Where the architecture manual specifies several formats for the
instruction (e.g., for jalr,
),use the one with more arguments
(i.e. two for jalr,
). When in doubt, see
arch/mips/testasm.fs
for an example of correct use.
Branches and jumps in the MIPS architecture have a delay slot. You
have to fill it manually (the simplest way is to use nop,
), the
assembler does not do it for you (unlike as
). Even
if,
, ahead,
, until,
, again,
,
while,
, else,
and repeat,
need a delay slot.
Since begin,
and then,
just specify branch targets, they
are not affected. For branches the argument specifying the target is
a relative address. Add the address of the delay slot to get the
absolute address.
Note that you must not put branches nor jumps (nor control-flow
instructions) into the delay slot. Also it is a bad idea to put
pseudo-ops such as li,
into a delay slot, as these may expand
to several instructions. The MIPS I architecture also had load delay
slots, and newer MIPSes still have restrictions on using mfhi,
and mflo,
. Be careful to satisfy these restrictions, the
assembler does not do it for you.
Some example of instructions are:
$ra 12 $sp sw, \ sw ra,12(sp) $4 8 $s0 lw, \ lw a0,8(s0) $v0 $0 lui, \ lui v0,0x0 $s0 $s4 $12 addiu, \ addiu s0,s4,0x12 $s0 $s4 $4 addu, \ addu s0,s4,$a0 $ra $t9 jalr, \ jalr t9
You can specify the conditions for if,
etc. by taking a
conditional branch and leaving away the b
at the start and the
,
at the end. E.g.,
4 5 eq if, ... \ do something if $4 equals $5 then,
The calling conventions for 32-bit MIPS machines is to pass the first
4 arguments in registers $4
..$7
, and to use
$v0
-$v1
for return values. In addition to these
registers, it is ok to clobber registers $t0
-$t8
without
saving and restoring them.
If you use jalr,
to call into dynamic library routines, you
must first load the called function’s address into $t9
, which
is used by position-indirect code to do relative memory accesses.
Here is an example of a MIPS32 abi-code
word:
abi-code my+ ( n1 n2 -- n3 ) \ SP passed in $4, returned in $v0 $t0 4 $4 lw, \ load n1, n2 from stack $t1 0 $4 lw, $t0 $t0 $t1 addu, \ add n1+n2, result in $t0 $t0 4 $4 sw, \ store result (overwriting n1) $ra jr, \ return to caller $v0 $4 4 addiu, \ (delay slot) return uptated SP in $v0 end-code