Show description
PLP Assembly: The Masterclass
PLP Assembly: The Masterclass
PLP MASTERCLASS
00. Start Here
01. The Hardware
02. The Assembly
03. Simulation Lab
04. Data & Logic
05. Mac Setup Guide
Welcome to the Machine
You are about to learn PLP (Progressive Learning Platform). This isn't just coding; this is moving electrons.
In high-level languages like Python, you ask the computer to do something. In Assembly, you tell the hardware exactly which wire to power.
The Mental Shift
Forget if statements and while loops for a moment. Think about:
Registers: A handful of super-fast storage boxes inside the CPU.
Memory: A giant wall of mailboxes far away from the CPU.
The ALU: A calculator that can only add/subtract two numbers at a time.
Navigate through the sidebar to master the machine.
01. The Hardware Architecture
To write Assembly, you must understand the "Stage" where your code performs.
The CPU Core
The PLP processor is based on the MIPS architecture. It has three main parts:
Control Unit (The Brain): Decodes your instructions. It sees addiu and flips the switches to set the ALU to "add" mode.
ALU (The Muscle): The Arithmetic Logic Unit. It crunches the numbers. It takes two inputs, does math, and spits out one result.
Registers (The Hands): Small, fast storage. The ALU can only work on data that is currently in a register.
The Cycle of Life (Fetch-Decode-Execute)
The CPU does this millions of times a second:
FETCH: The PC (Program Counter) points to a memory address. The CPU grabs the instruction code from there.
DECODE: The Control Unit figures out what the binary gobbledygook means (e.g., "Oh, this is a store word command").
EXECUTE: The data moves. The math happens. The PC increments to the next line.
02. The Instruction Set
You only have a few commands. Master them, and you can build anything.
The "Project 1" Essentials
These are the specific tools you need for the LED Counter project.
li $dest, value
Load Immediate. Puts a raw number into a register.
Ex: li $t0, 0xf0200000 (Put the LED address in $t0)
sw $src, offset($addr)
Store Word. Copies data from a register TO memory.
Ex: sw $t1, 0($t0) (Take value in $t1, send it to the address held in $t0)
addiu $dest, $src, value
Add Immediate Unsigned.…
PLP Assembly: The Masterclass
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PLP Assembly: The Masterclass</title>
<style>
:root {
--bg-dark: #0d1117;
--bg-panel: #161b22;
--border: #30363d;
--accent-green: #2ea043;
--accent-blue: #58a6ff;
--accent-purple: #bc8cff;
--accent-orange: #d29922;
--text-main: #c9d1d9;
--text-dim: #8b949e;
--led-off: #2a1111;
--led-on: #ff3333;
}
* { box-sizing: border-box; margin: 0; padding: 0; font-family: 'Courier New', Courier, monospace; }
body {
background-color: var(--bg-dark);
color: var(--text-main);
display: flex;
height: 100vh;
overflow: hidden;
}
/* --- Sidebar Navigation --- */
nav {
width: 250px;
background-color: var(--bg-panel);
border-right: 1px solid var(--border);
display: flex;
flex-direction: column;
padding: 1rem;
overflow-y: auto;
}
.nav-title {
color: var(--accent-green);
font-size: 1.2rem;
font-weight: bold;
margin-bottom: 2rem;
text-shadow: 0 0 10px rgba(46,160,67,0.2);
text-align: center;
border: 2px solid var(--accent-green);
padding: 0.5rem;
}
.nav-item {
padding: 0.8rem;
cursor: pointer;
color: var(--text-dim);
border-radius: 4px;
margin-bottom: 0.5rem;
transition: all 0.2s;
}
.nav-item:hover, .nav-item.active {
background-color: rgba(88, 166, 255, 0.1);
color: var(--accent-blue);
border-left: 3px solid var(--accent-blue);
}
/* --- Main Content Area --- */
main {
flex: 1;
padding: 2rem;
overflow-y: auto;
scroll-behavior: smooth;
}
section {
display: none; /* Hidden by default, JS toggles this */
animation: fadeIn 0.3s ease-in;
max-width: 900px;
margin: 0 auto;
}
section.active { display: block; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
h1 { color: var(--accent-blue); font-size: 2rem; margin-bottom: 1rem; border-bottom: 1px solid var(--border); padding-bottom: 0.5rem; }
h2 { color: var(--accent-purple); font-size: 1.5rem; margin: 2rem 0 1rem 0; }
h3 { color: var(--accent-orange); font-size: 1.2rem; margin: 1.5rem 0 0.5rem 0; }
p { margin-bottom: 1rem; line-height: 1.6; color: var(--text-main); }
ul { margin-left: 2rem; margin-bottom: 1rem; }
li { margin-bottom: 0.5rem; }
strong { color: var(--accent-green); }
code { background: rgba(110,118,129,0.4); padding: 2px 5px; border-radius: 4px; color: var(--accent-orange); }
.box {
background: var(--bg-panel);
border: 1px solid var(--border);
padding: 1.5rem;
border-radius: 8px;
margin-bottom: 1.5rem;
}
.warning-box {
border-left: 4px solid var(--accent-orange);
background: rgba(210, 153, 34, 0.1);
padding: 1rem;
margin: 1rem 0;
}
/* --- The Simulator --- */
.sim-dashboard {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
margin-top: 1rem;
}
.sim-comp {
background: #000;
border: 1px solid var(--border);
padding: 1rem;
border-radius: 4px;
}
.led-grid { display: grid; grid-template-columns: repeat(8, 1fr); gap: 5px; margin: 10px 0; }
.led { width: 25px; height: 25px; border-radius: 50%; background: var(--led-off); border: 2px solid #421; margin: 0 auto; transition: 0.1s; }
.led.on { background: var(--led-on); box-shadow: 0 0 15px #f00; border-color: #f88; }
.reg-row { display: flex; justify-content: space-between; border-bottom: 1px solid #333; padding: 5px 0; }
.reg-name { color: var(--accent-purple); font-weight: bold; }
.reg-val { color: var(--accent-green); font-family: monospace; }
.btn-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; margin-top: 1rem; }
button {
background: var(--bg-panel); border: 1px solid var(--accent-blue); color: var(--accent-blue);
padding: 10px; border-radius: 4px; cursor: pointer; font-weight: bold;
}
button:hover { background: var(--accent-blue); color: #fff; }
button.step-btn { border-color: var(--accent-green); color: var(--accent-green); }
button.step-btn:hover { background: var(--accent-green); color: #fff; }
.console {
background: #111; color: var(--accent-green); font-family: monospace; padding: 10px;
height: 120px; overflow-y: auto; border: 1px solid var(--border); margin-top: 10px; font-size: 0.85rem;
}
/* --- Hex Tool --- */
.converter { display: flex; gap: 10px; align-items: center; margin-top: 10px; }
input { background: #000; border: 1px solid var(--border); color: #fff; padding: 5px; }
</style>
</head>
<body>
<nav>
<div class="nav-title">PLP MASTERCLASS</div>
<div class="nav-item active" onclick="showSection('intro')">00. Start Here</div>
<div class="nav-item" onclick="showSection('hardware')">01. The Hardware</div>
<div class="nav-item" onclick="showSection('language')">02. The Assembly</div>
<div class="nav-item" onclick="showSection('lab')">03. Simulation Lab</div>
<div class="nav-item" onclick="showSection('data')">04. Data & Logic</div>
<div class="nav-item" onclick="showSection('mac')">05. Mac Setup Guide</div>
</nav>
<main>
<!-- SECTION 0: INTRO -->
<section id="intro" class="active">
<h1>Welcome to the Machine</h1>
<p>
You are about to learn <strong>PLP (Progressive Learning Platform)</strong>. This isn't just coding; this is moving electrons.
In high-level languages like Python, you ask the computer to do something. In Assembly, you <em>tell</em> the hardware exactly which wire to power.
</p>
<div class="box">
<h2>The Mental Shift</h2>
<p>Forget <code>if</code> statements and <code>while</code> loops for a moment. Think about: </p>
<ul>
<li><strong>Registers:</strong> A handful of super-fast storage boxes inside the CPU.</li>
<li><strong>Memory:</strong> A giant wall of mailboxes far away from the CPU.</li>
<li><strong>The ALU:</strong> A calculator that can only add/subtract two numbers at a time.</li>
</ul>
</div>
<p>Navigate through the sidebar to master the machine.</p>
</section>
<!-- SECTION 1: HARDWARE -->
<section id="hardware">
<h1>01. The Hardware Architecture</h1>
<p>To write Assembly, you must understand the "Stage" where your code performs.</p>
<div class="box">
<h2>The CPU Core</h2>
<p>The PLP processor is based on the MIPS architecture. It has three main parts:</p>
<ul>
<li><strong>Control Unit (The Brain):</strong> Decodes your instructions. It sees <code>addiu</code> and flips the switches to set the ALU to "add" mode.</li>
<li><strong>ALU (The Muscle):</strong> The Arithmetic Logic Unit. It crunches the numbers. It takes two inputs, does math, and spits out one result.</li>
<li><strong>Registers (The Hands):</strong> Small, fast storage. The ALU can <em>only</em> work on data that is currently in a register.</li>
</ul>
</div>
<div class="box">
<h2>The Cycle of Life (Fetch-Decode-Execute)</h2>
<p>The CPU does this millions of times a second:</p>
<ol>
<li><strong>FETCH:</strong> The <code>PC</code> (Program Counter) points to a memory address. The CPU grabs the instruction code from there.</li>
<li><strong>DECODE:</strong> The Control Unit figures out what the binary gobbledygook means (e.g., "Oh, this is a store word command").</li>
<li><strong>EXECUTE:</strong> The data moves. The math happens. The PC increments to the next line.</li>
</ol>
</div>
</section>
<!-- SECTION 2: ASSEMBLY LANGUAGE -->
<section id="language">
<h1>02. The Instruction Set</h1>
<p>You only have a few commands. Master them, and you can build anything.</p>
<div class="box">
<h3>The "Project 1" Essentials</h3>
<p>These are the specific tools you need for the LED Counter project.</p>
<ul>
<li>
<code>li $dest, value</code><br>
<strong>Load Immediate.</strong> Puts a raw number into a register.<br>
<em>Ex:</em> <code>li $t0, 0xf0200000</code> (Put the LED address in $t0)
</li>
<li>
<code>sw $src, offset($addr)</code><br>
<strong>Store Word.</strong> Copies data from a register TO memory.<br>
<em>Ex:</em> <code>sw $t1, 0($t0)</code> (Take value in $t1, send it to the address held in $t0)
</li>
<li>
<code>addiu $dest, $src, value</code><br>
<strong>Add Immediate Unsigned.</strong> Math time.<br>
<em>Ex:</em> <code>addiu $t1, $t1, 1</code> (Take $t1, add 1, put it back in $t1)
</li>
<li>
<code>j label</code><br>
<strong>Jump.</strong> Go to a specific bookmark (label) in the code.<br>
<em>Ex:</em> <code>j loop</code> (Go back to the start)
</li>
</ul>
</div>
<div class="box">
<h3>Advanced Tools (Good to Know)</h3>
<ul>
<li><code>beq $t0, $t1, label</code>: Branch if Equal. (If $t0 == $t1, go to label).</li>
<li><code>bne $t0, $t1, label</code>: Branch if Not Equal.</li>
<li><code>jal label</code>: Jump and Link. Used for functions (saves your spot in $ra).</li>
<li><code>jr $ra</code>: Jump Register. Used to return from a function.</li>
</ul>
</div>
</section>
<!-- SECTION 3: SIM LAB -->
<section id="lab">
<h1>03. Simulation Lab</h1>
<p>This is your interactive "Hello World" for hardware. We are simulating the <strong>LED Counter Project</strong>.</p>
<div class="sim-dashboard">
<div class="sim-comp">
<h3 style="margin-top:0">CPU State</h3>
<div class="reg-row"><span class="reg-name">PC (Instruction)</span> <span class="reg-val" id="pc-val">0x00</span></div>
<div class="reg-row"><span class="reg-name">$t0 (LED Addr)</span> <span class="reg-val" id="t0-val">0x00000000</span></div>
<div class="reg-row"><span class="reg-name">$t1 (Counter)</span> <span class="reg-val" id="t1-val">0x00</span></div>
</div>
<div class="sim-comp">
<h3 style="margin-top:0">I/O Board (0xf0200000)</h3>
<div class="led-grid" id="led-grid">
<!-- LEDs injected here -->
</div>
<div style="text-align:center; font-size:0.8rem; color:#666;">Binary Output Display</div>
</div>
</div>
<div class="console" id="sim-console">
> CPU INITIALIZED...<br>
> READY FOR INSTRUCTIONS...
</div>
<div class="btn-grid">
<button onclick="runStep(1)">1. LOAD ADDR (li $t0)</button>
<button onclick="runStep(2)">2. RESET COUNT (li $t1)</button>
<button class="step-btn" onclick="runStep(3)">3. STORE TO LED (sw)</button>
<button class="step-btn" onclick="runStep(4)">4. INCREMENT (addiu)</button>
</div>
<div class="warning-box">
<strong>Project Tip:</strong> In the real PLPTool, steps 3 and 4 happen inside a loop. You would press them repeatedly to see the count go up!
</div>
</section>
<!-- SECTION 4: DATA LOGIC -->
<section id="data">
<h1>04. Data Representation</h1>
<p>Computers don't know "15". They know <code>0000 1111</code>.</p>
<div class="box">
<h2>Hexadecimal Crash Course</h2>
<p>We use Hex (Base-16) because binary is too long to read. One Hex digit = 4 Binary bits.</p>
<div class="converter">
<span>Decimal:</span> <input type="number" id="dec-input" oninput="convertDec()">
<span> = Hex: 0x</span><span id="hex-output" style="color:var(--accent-orange)">00</span>
<span> = Binary: </span><span id="bin-output" style="color:var(--accent-green)">00000000</span>
</div>
</div>
<div class="box">
<h2>2's Complement (Signed Numbers)</h2>
<p>How do we store -5? We can't use a minus sign.</p>
<ol>
<li>Take the positive number in binary (5 = <code>0000 0101</code>).</li>
<li>Flip all bits (<code>1111 1010</code>).</li>
<li>Add 1 (<code>1111 1011</code>).</li>
</ol>
<p><strong>Result:</strong> <code>0xFB</code> is -5 in a byte.</p>
</div>
</section>
<!-- SECTION 5: MAC SETUP -->
<section id="mac">
<h1>05. Mac Users: The Automator Hack</h1>
<div class="warning-box">
<strong>Problem:</strong> macOS doesn't like opening <code>.plp</code> files directly with Java JARs.
<br><strong>Solution:</strong> We build a custom launcher app.
</div>
<div class="box">
<h3>Step-by-Step Fix</h3>
<ol>
<li>Open <strong>Automator</strong> on your Mac.</li>
<li>Create a new document type: <strong>Application</strong>.</li>
<li>Search for <strong>"Run Shell Script"</strong> and drag it to the workflow.</li>
<li>Change "Pass input" to <strong>"as arguments"</strong>.</li>
<li>Paste this code into the script box:
<pre style="background:#000; padding:10px; margin:5px 0; color:var(--accent-green)">
for f in "$@"
do
java -jar /path/to/PLPToolStatic.jar "$1"
done
</pre>
<em>(Replace <code>/path/to/...</code> with the actual location of your jar file!)</em>
</li>
<li>Save the app as "PLPLauncher".</li>
<li>Right-click any <code>.plp</code> file -> <strong>Get Info</strong> -> Open With -> Select your new PLPLauncher app -> Click <strong>Change All</strong>.</li>
</ol>
<p>Now you can double-click your project files like a pro!</p>
</div>
</section>
</main>
<script>
// --- Navigation Logic ---
function showSection(id) {
document.querySelectorAll('section').forEach(s => s.classList.remove('active'));
document.getElementById(id).classList.add('active');
document.querySelectorAll('.nav-item').forEach(n => n.classList.remove('active'));
event.target.classList.add('active');
}
// --- Simulator Logic ---
let simState = { t0: 0, t1: 0, pc: 0 };
const consoleEl = document.getElementById('sim-console');
const gridEl = document.getElementById('led-grid');
// Init LEDs
for(let i=7; i>=0; i--) {
let led = document.createElement('div');
led.className = 'led';
led.id = 'led-'+i;
gridEl.appendChild(led);
}
function log(msg) {
consoleEl.innerHTML += `> ${msg}<br>`;
consoleEl.scrollTop = consoleEl.scrollHeight;
}
function updateDisplay() {
document.getElementById('t0-val').innerText = '0x' + simState.t0.toString(16).toUpperCase();
document.getElementById('t1-val').innerText = '0x' + simState.t1.toString(16).toUpperCase().padStart(2, '0');
// Update LEDs based on t1 value IF it was just stored
// In this simple sim, we update visuals based on the register for feedback
}
function updateLEDs(val) {
for(let i=0; i<8; i++) {
let on = (val >> i) & 1;
let el = document.getElementById('led-'+i);
if(on) el.classList.add('on');
else el.classList.remove('on');
}
}
function runStep(step) {
switch(step) {
case 1:
simState.t0 = 0xf0200000;
log("Instruction: li $t0, 0xf0200000");
log("--> $t0 now holds address of LEDs");
break;
case 2:
simState.t1 = 0;
log("Instruction: li $t1, 0");
log("--> Counter initialized to 0");
updateLEDs(0);
break;
case 3:
if(simState.t0 === 0) { log("ERROR: Address not loaded! Run Step 1."); return; }
log(`Instruction: sw $t1, 0($t0)`);
log(`--> Writing value ${simState.t1} to LEDs`);
updateLEDs(simState.t1);
break;
case 4:
simState.t1 = (simState.t1 + 1) % 256;
log(`Instruction: addiu $t1, $t1, 1`);
log(`--> Counter is now ${simState.t1}`);
break;
}
updateDisplay();
}
// --- Converter Logic ---
function convertDec() {
let val = parseInt(document.getElementById('dec-input').value);
if(isNaN(val)) val = 0;
document.getElementById('hex-output').innerText = val.toString(16).toUpperCase();
document.getElementById('bin-output').innerText = val.toString(2).padStart(8, '0');
}
</script>
</body>
</html>