First of all, I’d like to warmly welcome all of you who found out about my blog to read what I write here (^∀^●)ノシ. You might wonder why I’m writing about this MIPS assembly language, as it’s not exactly a new topic and I’m writing about it again 🙁. The reason here is that I’m currently interested in researching and exploring the intricacies of IoT devices (especially Wi-Fi routers). So, as you might already know, IoT devices often use the MIPS architecture for their RISC instruction set.
Speaking of instruction sets, there are two types: CISC and RISC.
- CISC is mainly used in personal computers and servers because its instruction set is extensive and quite complex, leading to resource and power consumption. That’s why IoT devices aren’t so exciting?)
- In contrast, RISC is less and simpler, consuming fewer resources and less power, making it suitable for IoT devices or mobile devices.
Enough of that babble, let’s dive into today’s main topic.
MIPS assembly language.
After several upgrades, MIPS now has two versions: 32-bit and 64-bit. However, this article and later I will concentrate solely on the 32-bit version because of the simplicity, and I’m also learning about it, so please understand ^^.
MIPS has a total of 32 registers for storing values, numbered from 0 to 31, along with a common convention when used. Among them, register 0 is always hard-assigned with the value 0.
Register | Common Name | Meaning |
$0 | $zero | The registers always contain the value 0 |
$1 | $at | Reserved for assembler |
$2 – $3 | $v0,$v1 | Saves the return values of a function |
$4 – $7 | $a0-$a3 | Saves arguments passed to functions |
$8 – $15 | $t0 – $t7 | Saves temporary variables |
$16 – $23 | $s0 – $s7 | Saves register values |
$24 – $25 | $t8 – $t9 | Similar to registers $8 – $15 |
$$26 -$27 | $k0 – $k1 | Reserved for kernel. Not for general use. |
$28 | $gp | Points to the global area (Global Area Pointer) |
$29 | $sp | Stack Pointer |
$30 | $fp | Frame Pointer |
$31 | $rp | Return Address |
MIPS Instruction Format:
In some processors, particularly CISC processors, the size of an instruction varies based on the instruction itself and its operands.
However, MIPS, like most RISC processors, employs fixed-length instruction formats. All MIPS instructions are precisely 32 bits long. The fixed-length instructions provide the advantage of simpler instruction fetching, which translates to smaller and cheaper processors. Simpler and smaller leads to faster performance, lower power consumption, and reduced production costs.
Register Instructions:
Register instructions involve two source registers and one destination register.
Register Instruction Format.
Opcode | Source 1 | Source 2 | Destination | Shift Amount | Function |
000000 | 5 bits | 5 bits | 5 bits | 5 bits | 6 bits |
Explanation:
Opcode (6 bits): This register contains 6 bits set to 0, indicating that this is a register instruction (RI).
Function (6 bits): This register uses 6 bits to differentiate between different instruction types.
Source 1, Source 2 (10 bits): These two registers, each consisting of 10 bits, represent the source registers used for performing computations.
Destination (5 bits): This field stores the computed result.
Shift Amount (5 bits): The number of bits to shift left or right when there’s a bit shift instruction
Example: add $t3, $t4, $t1
Where: $t3 = 11, $t4 = 12, $t1 = 9
000000 | 01100 | 01001 | 01011 | 00000 | 10000 |
RI | $t4 | $t1 | $t3 | unused | add |
Jump Instructions
Opcode | Target Offset |
0001xx | 26 bits |
In the case if the leftmost 6 bits are 00001x, then this is an unconditional jump instruction.
Example:
000010 xxxxxxxxxxxxxxxxxxxxxxxxxx ~ j label
000011 xxxxxxxxxxxxxxxxxxxxxxxxxx ~ jal label
Looking at this, you might wonder how, with 26 bits, it’s possible to jump to the 32-bit destination address. The target address expansion to 32 bits occurs dynamically at runtime when the jump instruction is executed. The destination address field converts to a 32-bit address, be occurs at runtime when the jump instruction is executed.
Coprocessor Instructions
If the leftmost 6 bits are 0100xx, the instruction is processed by the coprocessor (an extension for the basic MIPS CPU). The last two bits represent the coprocessor.
Opcode | Source 1 | Source 2 | Destination | Shift Amount | Function |
0100xx | 5 bits | 5 bits | 5 bits | 5 bits | 6 bits |
Immediate Instructions
If the leftmost 6 bits differ from all above, the instruction is used for the immediate format.
Immediate instructions use one source register, one destination register, and a 16-bit immediate operand.
The immediate operand is limited to 16 bits, allowing unsigned values from 0 to 65535 or signed values from -32768 to 32767 (MIPS processors use two’s complement for signed operands).
Opcode | Source | Destination | Immediate Operand |
0100xx | 5 bits | 5 bits | 16 bits |
For example: addi $t1, $t5, 7
Opcode | Source | Destination | Immediate Operand |
001000 | sssss | ttttt | 0000000000000111 |
addi | $t1 | $t5 | 7 |
And that concludes the article. The main purpose of this piece was to provide a brief and general introduction to the MIPS assembly language. In the upcoming articles, I will explai the details of the instructions that I consider crucial within MIPS :D. This will be a long-term series, so if you find it informative, please giving me a like and subscribe ^^.
Reference link: