Assignment Chef icon Assignment Chef
All English tutorials

Programming lesson

Building a Dollar Store Calculator in MIPS Assembly: A Step-by-Step Guide

Learn to build a simple integer calculator in MIPS assembly using MARS tools. This tutorial covers keypad input, LCD output, state machines, and arithmetic without multiplication/division instructions.

MIPS assembly calculator Cs 0447 project MARS calculator tool assembly language tutorial integer calculator MIPS state machine assembly MIPS keypad input MIPS LCD output multiplication without mul MIPS division without div MIPS MIPS polling loop embedded systems assembly MIPS register usage calculator state machine MIPS arithmetic without mul MIPS programming project

Introduction: Why Build a Calculator in Assembly?

In today's world of high-level languages and AI-powered apps, you might wonder why anyone would write a calculator in MIPS assembly. But understanding how hardware interacts with software at the lowest level is crucial for fields like embedded systems, game development, and even cryptocurrency mining. This tutorial walks you through building a dollar store calculator using MARS tools—just like the classic Cs 0447 project. You'll learn to handle keypad input, display numbers on an LCD, and implement arithmetic without multiplication or division instructions. By the end, you'll have a working calculator that feels like something from a 1980s arcade game!

Understanding the Simple Calculator Tool

The MARS tool provides a virtual calculator with an LCD display connected to register $t8 and a keypad connected to $t9. When a button is pressed, $t9 gets the value: bit 31 set to 1, and bits 0-3 encode the button (0-9, +, -, *, /, =, C). Your program must poll $t9 in a loop until it's non-zero, then decode the input. After processing, you must reset $t9 to 0 to enable the next press.

State Machine Design

Your calculator behaves like a finite state machine with four states (0-3). In State 0, you wait for a digit or clear. State 1 builds the first operand. State 2 expects an operator. State 3 builds the second operand. Pressing '=' computes the result and goes to State 4 (display result). Pressing 'C' resets everything. This design is similar to how a vending machine processes coins—each input changes the state until you get a product.

Step 1: Displaying a Single Digit

Start by writing code that reads a keypad press and displays the corresponding digit on the LCD. For example, if the user presses '5', $t9 becomes 0x80000005. Your code should extract the lower 4 bits, store them in $t8, and reset $t9 to 0. Use andi to mask the lower nibble: andi $t0, $t9, 0xF. Then move $t0 to $t8. Test this before moving on.

Step 2: Building Multi-Digit Numbers

To handle numbers like 529, you need to accumulate digits: operand = operand * 10 + digit. Since you can't use mul, use shifts and adds: operand * 10 = (operand << 3) + (operand << 1). For example, if operand is 5 and you press '2', new operand = 5*10+2 = 52. In assembly: sll $t1, $s0, 3 (operand*8), sll $t2, $s0, 1 (operand*2), add $s0, $t1, $t2 (operand*10), then add $s0, $s0, $t0 (add digit). Display $s0 via $t8.

Step 3: Handling Operators and Clear

When the user presses '+', '-', '*', or '/', store the operator code (e.g., 10 for +) in a register like $s1. Move the current operand to $s2 (operand1) and reset operand accumulator to 0. For 'C', clear all registers and display 0. For '=', compute the result using the stored operator and operands. Remember to implement multiplication and division using loops—no mul or div instructions allowed!

Step 4: Multiplication Without Multiply

To multiply two numbers, use repeated addition. For example, result = 0; for(i=0; i. In assembly, use a loop with beq and add. Be careful with negative numbers—you can handle sign separately. This is like calculating the total cost of multiple items in a shopping app: add the price repeatedly.

Step 5: Division Without Divide

Integer division can be done by repeated subtraction: quotient = 0; while(dividend >= divisor) { dividend -= divisor; quotient++; }. The remainder is the final dividend. This is similar to counting how many times you can fill a cup from a water jug. Watch out for division by zero—display an error or just loop forever (but in this project, assume valid input).

Putting It All Together

Now combine all pieces into a single program. Use registers $s0 for current operand, $s1 for operator, $s2 for operand1, $s3 for operand2, $s4 for result, and $s5 for state. Use labels like state0, state1, etc. Remember: no jal/jr, no memory, no syscalls. Your program runs indefinitely, polling the keypad. This is a classic embedded system pattern—like the firmware in a smart thermostat or a fitness tracker.

Testing Your Calculator

Test with simple operations: 5+3=8, 10-4=6, 7*3=21, 9/2=4 (integer division). Then test multi-digit: 123+456=579. Then test operator chaining: 5+*3=15 (because last operator is *). Also test clear: press C between operations. If something fails, use the MARS debugger to step through your code. This is like debugging a mobile app—check each state transition.

Common Pitfalls and Tips

Don't forget to reset $t9 to 0 after reading input, otherwise the calculator will think the same button is pressed repeatedly. Also, when building multi-digit numbers, ensure you handle the transition from operand1 to operand2 correctly—the state machine helps. Use slt for comparisons and beq/bne for branching. Avoid pseudo-instructions like li or move—use addi and add instead. This project is a rite of passage for computer architecture students, similar to building a simple CPU in a logic simulator.

Real-World Connections

This calculator project mirrors the logic in many modern devices: ATMs, point-of-sale systems, and even the number pad on your smartphone's dialer. Understanding polling and state machines is essential for IoT devices like smart home hubs. In gaming, input handling often uses similar polling loops. And in the world of AI, tensor processing units (TPUs) perform massive parallel arithmetic—but they started with simple adders like yours!

Conclusion

You've built a fully functional integer calculator in MIPS assembly. You've learned to handle hardware I/O, implement arithmetic without dedicated instructions, and design a state machine. This foundation will serve you well in advanced courses like operating systems, compilers, and embedded systems. Now go ahead and impress your friends by showing them a calculator that runs on virtual hardware—it's the ultimate retro computing flex!