Category:MIPS Assembly

From Rosetta Code
Revision as of 19:03, 4 July 2022 by Puppydrum64 (talk | contribs)
This page is a stub. It needs more information! You can help Rosetta Code by filling it in!
Language
MIPS Assembly
This programming language may be used to instruct a computer to perform a task.


Listed below are all of the tasks on Rosetta Code which have been solved using MIPS Assembly.

MIPS architecture

Registers

MIPS has a whopping 32 registers. Most of them are technically general purpose but calling conventions dictate what each should be used for. Unlike most assembly languages, where you have to remember what the calling conventions are, MIPS assemblers typically give the registers abbreviated names that imply how to use them. For example, $v0 and $v1 are the return values of functions, and $a0 through $a3 are function arguments. While a frame pointer does exist, having four registers dedicated to passing function arguments means you won't have to twiddle around with stack frames nearly as much as you would on other CPUs.


Pseudo-instructions

MIPS has a form of "hardware macros" that help out with tasks that it can't do alone. It has a special register that exists solely for the execution of these macros, which is not usable by the programmer directly. Assemblers will generally let you use these "pseudo-instructions" as if they were real instructions, even if they technically don't exist. Knowing what instructions are "real" and which ones aren't usually doesn't matter much, since you won't be doing self-modifying code on the MIPS anyway (for reasons we'll get into later)

Alignment

Unlike other RISC CPUs, MIPS actually can load data from unaligned memory without faulting. However, it can't use the normal LW and SW commands in order to do so. It should be noted that this only applies to data; instructions do need to be 32-bit aligned at all times. Most assemblers have an .align directive that can do the job easily.

Bi-Endian

MIPS's endianness is not set in stone like the x86 or Motorola 68000. Different MIPS CPUs can have different endianness. For example, the PlayStation 1's CPU is little-endian, whereas the Nintendo 64 is big-endian.

Out-of-Order Execution

MIPS uses an instruction pipeline, which means that while an instruction is finishing up, the one after it is currently being executed. 8-bit CPUs, and some early 16-bit CPUs didn't have pipelining like this. On those machines, the only instruction being executed is the current one, and anything after it may as well not exist. This is not the case with MIPS, as it starts executing the next instruction before the current one finishes. This is very common for most CPUs today, as it makes the CPU much faster. However, pipelining fundamentally changes how branches must be handled.

Load Delay Slots

This is only a concern on the first generation of MIPS hardware. When loading a value from memory, the register that is loaded with the value won't actually have it by the time the next instruction has already been executed. The way around this is to place a NOP after the load, or alternatively, an instruction that doesn't depend on the new value of that register.

<lang mips> lw t0,(a0) addiu t0,1 ;when this instruction is executed, t0 hasn't updated yet with its value from the previous instruction.</lang>

The Nintendo 64 doesn't have to worry about load delay slots, but the PlayStation 1 does, therefore care must be taken when programming for that system. (Chances are you're programming in C anyway, which would take care of all this for you, but still.)

Branch Delay Slots

Branch delay slots affect all versions of MIPS. This is the phenomenon where the instruction immediately after a branch is actually executed before the branch takes place. <lang mips>jal PrintString addiu $a0,1 ;this instruction is executed BEFORE the call to PrintString is.</lang>

This would have the same outcome as the following, except the above version is faster than this one: <lang mips>addiu $a0,1 jal PrintString nop</lang>