Wrote a quick manual.

master
Zed A. Shaw 4 years ago
parent be31c0ed20
commit 1cd84af248
  1. 6
      src/components/Footer.svelte
  2. 2
      src/components/Nav.svelte
  3. 4
      src/components/Sidebar.svelte
  4. 2
      src/node_modules/buttons.js
  5. 7
      src/routes/index.svelte
  6. 335
      src/routes/manual.svelte

@ -20,10 +20,11 @@
font-size: 20px !important; font-size: 20px !important;
text-shadow: 2px 2px $gray-color-dark; text-shadow: 2px 2px $gray-color-dark;
} }
</style> </style>
<div id="footer" class="columns col-gapless"> <div id="footer" class="columns col-gapless">
<div class="column col-9"> <div class="column col-8">
<div class="panel"> <div class="panel">
<div class="panel-header"> <div class="panel-header">
This website and all content is Copyright &copy; Zed A. Shaw since 2020 and beyond. This website and all content is Copyright &copy; Zed A. Shaw since 2020 and beyond.
@ -33,8 +34,9 @@
</div> </div>
</div> </div>
<div class="column col-3" id="right-column"> <div class="column col-4" id="right-column">
<a alt="Twitter @lzsthw" aria-label="Twitter @lzsthw" rel="external" href="https://twitter.com/lzsthw"><Icon size="48" name="twitter" light={true} /></a> <a alt="Twitter @lzsthw" aria-label="Twitter @lzsthw" rel="external" href="https://twitter.com/lzsthw"><Icon size="48" name="twitter" light={true} /></a>
<a alt="The git repository" aria-label="The git repository" rel="external" href="https://git.learnjsthehardway.com/zedshaw/buttons-computer"><Icon size="48" name="code" light={true} /></a> <a alt="The git repository" aria-label="The git repository" rel="external" href="https://git.learnjsthehardway.com/zedshaw/buttons-computer"><Icon size="48" name="code" light={true} /></a>
<a alt="Read the blog" aria-label="Read the blog" rel="external" href="https://git.learnjsthehardway.com/zedshaw/buttons-computer"><Icon size="48" name="book-open" light={true} /></a>
</div> </div>
</div> </div>

@ -36,7 +36,7 @@
<a data-testid='nav-home-icon' rel="prefetch" class:btn-link="{ segment != undefined }" class="btn" href="/" alt="Home" aria-label="Home"> <a data-testid='nav-home-icon' rel="prefetch" class:btn-link="{ segment != undefined }" class="btn" href="/" alt="Home" aria-label="Home">
<Icon name="home" size="32" tooltip="Home" tooltip_bottom={true} light={true}/> <Icon name="home" size="32" tooltip="Home" tooltip_bottom={true} light={true}/>
</a> </a>
<a data-testid='nav-blog-icon' rel="external" class:btn-link="{ segment != 'blog' }" class="btn" href="https://learnjsthehardway.com/blog" alt="Read the blog" aria-label="Read the blog"> <a data-testid='nav-manual-icon' class:btn-link="{ segment != 'manual' }" class="btn" href="manual" alt="Read the manual" aria-label="Read the blog">
<Icon name="book-open" size="32" tooltip="Blog" tooltip_bottom={true} light={true} /> <Icon name="book-open" size="32" tooltip="Blog" tooltip_bottom={true} light={true} />
</a> </a>
</section> </section>

@ -22,5 +22,9 @@ REGISTERS:
{#each registers as reg} {#each registers as reg}
{ reg + '\n'} { reg + '\n'}
{/each} {/each}
GOOD LUCK!
</code> </code>
</pre> </pre>

2
src/node_modules/buttons.js generated vendored

@ -154,7 +154,7 @@ class ButtonMachine {
if(!this.assert(reg_names.includes(reg), `Register "${reg}" is not valid. Use ${reg_names}`)) return; if(!this.assert(reg_names.includes(reg), `Register "${reg}" is not valid. Use ${reg_names}`)) return;
let val = this.registers[reg]; let val = this.registers[reg];
this.assert(val !== undefined, `Invalid register ${reg}`); this.assert(val !== undefined, `Invalid register ${reg} or register empty.`);
this.stack.push(val); this.stack.push(val);
this.next(); this.next();

@ -54,7 +54,8 @@
const clone_line = (i) => { const clone_line = (i) => {
let clone = code[i]; let clone = code[i];
code.splice(i, 0, [...clone]); // whew! clone the array without the 2nd one so it's empty
code.splice(i+1, 0, [clone[0]]);
code = code; code = code;
} }
@ -186,7 +187,7 @@
<div class="column col-6 col-sm-12 col-md-12 col-xs-12" id="status-panel"> <div class="column col-6 col-sm-12 col-md-12 col-xs-12" id="status-panel">
<pre id="machine-state"> <pre id="machine-state">
<code> <code>
IP {machine.ip} █TICK { machine.tick} LINE {machine.ip} █TICK { machine.tick}
{#if machine.halted }<span class="error">HALT! { machine.error }</span>{/if} {#if machine.halted }<span class="error">HALT! { machine.error }</span>{/if}
╞ STACK ╡ ╞ STACK ╡
@ -200,7 +201,7 @@
╞ REGISTERS ╡ ╞ REGISTERS ╡
────────────────── ──────────────────
{#each registers as reg } {#each registers as reg }
[{ reg }]={ (machine.registers[reg] || '█') + '\n'} [{ reg }]={ (machine.registers[reg] !== undefined ? machine.registers[reg] : '█') + '\n'}
{/each} {/each}
</code> </code>
</pre> </pre>

@ -0,0 +1,335 @@
<script>
import {goto, stores} from '@sapper/app';
import Icon from '../components/Icon.svelte';
</script>
<svelte:head>
<title>Buttons the Computer - The Manual</title>
</svelte:head>
<style lang="scss">
@import "sass/_variables";
#content {
margin-top: 1rem;
font-size: 20px;
}
code {
font-size: 20px;
text-shadow: 2px 2px $gray-color;
color: lighten($green, 20%);
}
blockquote {
color: $green;
background: $gray-color-dark;
font-family: 'Tandy1KMono';
text-shadow: 2px 2px $black;
}
pre code {
color: lighten($green, 20%);
background: $gray-color-dark;
font-family: 'Tandy1KMono';
text-shadow: 2px 2px $black;
}
</style>
<div class="container grid-lg" id="content" data-testid="manual-page">
<div class="columns">
<div class="column col-12">
<h1>The Manual</h1>
<p>
<code>BUTTONS</code> is a tiny computer that you can program entirely with a 2 button mouse by clicking on buttons.
It features all of the operations you need to learn about computers and how they process numbers. All you need to
do is click on the right buttons and make <code>BUTTONS</code> do the math.
</p>
<h2>Stacking Plates</h2>
<p>Imagine if I handed you a stack of dinner plates and told you to
number each one. I give you a grease pen and a <code>STACK</code> of 10
plates and tell you to get to work. How would you number these plates?
When you were done how would the plates be stacked? Let's call the
unnumbered plates <code>new plates</code> and your stack of numbered
plates <code>done plates</code>.</p>
<p>You would probably take the first plate off the top of the stack of
plates, write the number <code>1</code> on it, and then set it to the
side in the <code>done plates</code> stack. You can't put it back on the
<code>new plates</code> stack of plates because then you wouldn't make
your way through the plates. You take one off the <code>top</code> of
the <code>new plates</code>, write the number <code>2</code>, and put it
on <code>top</code> of the stack of plates called <code>done
plates</code>. You then do this with #3, #4, #5, until you are done
going through all 10 plates.</p>
<p>You then look over at your stack of numbered <code>done plates</code>
and you're happy, but the plate on <code>top</code> is numbered 20.
You've stacked them in reverse, and you probably need to re-stack them in
order. How would you do that? Well, you simply take one off the top of
the <code>done stack</code> and put it onto another stack (let's call
that <code>sorted</code>) until you're out of plates. Now <code>sorted
stack</code> is numbered 1-10, with 1 on <code>top</code>.</p>
<p>Try this with 10 pieces of paper instead of dinner plates. Cut up 10 little cards that do
<b>not</b> have numbers on them, and then write the numbers 1-10 on each piece of paper and stack
it just like above. Then restack them again to get them in the sorted order. <b>This</b> is a
stack and it's used in computers and in <code>BUTTONS</code>.</p>
<h2>PUSH & POP</h2>
<p>The way <code>BUTTONS</code> remembers what it's doing is with a
<code>STACK</code>. A <code>STACK</code> is a very simple storage system
that takes numbers one at a time and puts them on top of each other, just
like with the dinner plates in the previous explanation. Numbers are
pushed onto <code>BUTTONS'</code> version of a <code>STACK</code> and the
<b>last one in is the first one out</b>.</p>
<blockquote><Icon name="alert-circle" color="#f00" />
You should go get a note book and write these things down. Be sure to
write, "A stack is a last in, first out number storage. The last number
I push onto the stack is the first number to come out." I say this
because I actually got this wrong in the first implementation of the
stack, so if I can get it wrong, so can you.</blockquote>
<p>You <code>PUSH</code> numbers onto the <code>STACK</code>, then call
other operations (<code>ADD</code> for example) to make
<code>BUTTONS</code> do math on them. When you <code>PUSH</code> you
have to give it the number it should push onto the <code>top</code> of
the <code>STACK</code>. On the right you'll then see
<code>BUTTONS</code> show that number under the <code>STACK</code>
output. </p>
<p>The <code>POP</code> operation simple takes any number that's on the <code>top</code> of
the <code>STACK</code> and removes it. Junks it. Throws it away. If you try to <code>POP</code>
too much your <code>BUTTONS</code> will crash. Don't do that.</p>
<h2>Math</h2>
<p>You can now <code>PUSH</code> numbers onto the <code>STACK</code> and use <code>POP</code> to take
them off. Big deal. That's not a computer...yet. The next piece of our puzzle game is to let you do <b>math</b>
with these numbers on the <code>STACK</code>. <code>BUTTONS</code> has the following simple operations:</p>
<table class="table">
<thead>
<tr>
<th>OPERATION</th><th>MATH</th><th>DESCRIPTION</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>ADD</code></td> <td>a + b</td> <td>Adds two numbers</td>
</tr>
<tr>
<td><code>SUB</code></td> <td>a - b</td> <td>Subtracts two numbers</td>
</tr>
<tr>
<td><code>MUL</code></td> <td>a * b</td> <td>Multiplies two numbers</td>
</tr>
<tr>
<td><code>DIV</code></td> <td>a / b</td> <td>Divides two numbers</td>
</tr>
<tr>
<td><code>MOD</code></td> <td>a % b</td> <td>Modulus of two numbers</td>
</tr>
</tbody>
</table>
<p>The order of each operation is the same, with <b>a</b> being
<code>PUSH</code> on first, then <b>b</b>. That means when you're done
your <b>b</b> number should be on the <code>top</code> of the
<code>STACK</code>. Here's how I would add <code>1 + 2</code>:</p>
<pre>
<code>
0: PUSH 1
1: PUSH 2
2: ADD
</code>
</pre>
<p>When you run these lines of code in <code>BUTTONS</code> the number <code>3</code> will be at the top of the stack
ready to use. You can also try <code>POP</code> to remove it and see how that works.</p>
<blockquote><Icon name="alert-circle" color="#f00" />
When you see the <code>0:</code> at the front of the line that's the line number. It's not code, just me being lazy and not wanting to implement line numbers in fancy CSS.
</blockquote>
<h2>TICKS</h2>
<p>Before we get into loops I have to warn you that <code>BUTTONS</code>
is not a very powerful computer. It can only perform <code>128</code>
operations before it runs out of energy called <code>TICKS</code>. If
your computer runs this many ticks then <code>BUTTONS</code> will stop
running and give up.</p>
<h2>Looping with JUMP</h2>
<p>To make a computer we need a way to repeatedly run code so we can do many calculations. <code>BUTTONS</code> has
the operation <code>JUMP</code> that will jump to the line you give, then keep running. If I want to run a loop that counts from 1 to 128 I can do this in <code>BUTTONS</code>:
<pre>
<code>
0: PUSH 1
1: PUSH 1
2: ADD
3: JUMP 1
</code>
</pre>
<p>You really should <b>study</b> this simple little program because inside it's simplicity is an incredibly powerful idea. Here's some questions to ask while you study:</p>
<ol>
<li>Why do I do <code>JUMP 1</code> instead of <code>JUMP 2</code> to reach the <b>second</b> line?</li>
<li>Step through the code and write down what the top of the stack is at each step.</li>
<li>If you want to go up by a different count what do you do?</li>
<li>How does this work with <code>SUB, DIV, MUL, and MOD</code> operations?</li>
</ol>
<p>Play with this code in <code>BUTTONS</code> until you understand what's going on because if you don't get
<code>JUMP</code> then you <b>definitely</b> won't understand the next section.</p>
<blockquote><Icon name="alert-circle" color="#f00" />
You can also <code>JUMP</code> one line <b>past</b> the end of your code to end your program. That means if you have 4 lines of code, then you can do <code>JUMP 5</code> and end your program. This becomes important later so write this down in your notebook too.
</blockquote>
<h2>Logic with JZ/JNZ</h2>
<p>You now know how to make <code>BUTTONS</code> do math, use the <code>STACK</code>, and do a loop to do lots of math. There's <b>one</b> last thing we need before we have a real working computer and that's the idea of a <code>test</code> and jumping only if that test is true (or false).</p>
<p>Let's say you have the following code that counts <b>down</b> from 10 to 0:</p>
<pre>
<code>
0: PUSH 10
1: PUSH 1
2: SUB
3: JUMP 1
</code>
</pre>
<p>You run it, thinking it will stop at zero, and instead
<code>BUTTONS</code> does exactly what you told it to do and keeps going
until it runs out of <code>TICKS</code>, leaving .... <code>-32</code> on
the top? What?!</p>
<p>The reason is you have no way to tell <code>BUTTONS</code> when to stop. You can tell it to do the math and where to <code>JUMP</code> but you have no way to tell buttons "when you reach 0 on the <code>STACK</code> you should stop." You do this with the <code>JZ</code> operation which means "<code>JUMP if Zero</code>". It simply looks at the top of the <code>STACK</code> and if that's 0 then it does a <code>JUMP</code> to where you want. This is doing a test of the top of stack, and a jump. Now we can rewrite our program like this:</p>
<pre>
<code>
0: PUSH 10
1: PUSH 1
2: SUB
3: JZ 5
4: JUMP 1
</code>
</pre>
<p>See how line 3 is now <code>JZ 5</code>, but right after that on line
4 we have <code>JUMP 1</code>? This seems very backwards, but we have to do this because we want
line 3 to <b>only</b> <code>JUMP 1</code> to the end (line 5 is the end) when the <code>STACK</code>
is 0. It's working as a "guard" that prevents line 4 <code>JUMP 1</code> from running when the <code>STACK</code>
is 0. Another way to see this is it will "jump over" line 4 <code>JUMP 1</code> when the <code>STACK</code> is 0.</p>
<p>We can simplify this by using another operation called <code>JNZ</code> which does the inverse of <code>JZ</code> and "jumps if <b>NOT</b> zero". Using this operation we can now have:</p>
<pre>
<code>
0: PUSH 10
1: PUSH 1
2: SUB
3: JNZ 1
</code>
</pre>
<p>Instead of that weird "jump over the next line that's a jump if the
stack is zero" in the previous program, we have "jump to line 1 if stack
is not zero". Way easier to do, but keep in mind you many times need
both. Both effectively do the same thing but it's sometimes easier to use
one or the other (<code>JZ</code> vs. <code>JNZ</code>) depending on how
you're doing the operation.</p>
<h2>STOR/RSTOR Registers</h2>
<p>You technically can do all of the computation you need with just that (minus input and output), but it's really annoying and hard to do much more than add some numbers in loops. To make it possible to implement larger more complex prgrams in <code>BUTTONS</code> you have four <code>REGISTERS</code> where you can keep temporary variables for later: <code>AX, BX, CX, DX</code>. I named them this way just for old time's sake, and to keep things simple. You put things into these registers (and take them out) using the <code>STOR</code> and <code>RSTOR</code> (for "restore") operations:</p>
<table class="table">
<thead>
<tr>
<th>OPERATION</th><th>DESCRIPTION</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>STOR</code></td><td><b>Copies</b> the <code>STACK</code> top to the named register.</td>
</tr>
<tr>
<td><code>RSTOR</code></td><td><code>PUSH</code> the number in the named register onto the <code>STACK</code>.</td>
</tr>
</tbody>
</table>
<p>Let's say I want to count down like before, but I want to keep track of the previous number as you go. I don't know why. You just do. Ok, here's how:</p>
<pre>
<code>
0: PUSH 10
1: STOR AX
2: PUSH 1
3: SUB
4: JNZ 1
</code>
</pre>
<p>Now as you step through this program you can watch the <code>AX</code> register keep the previous stack top as it goes. Let's say you want to keep the initial value you started with for after the loop:</p>
<pre>
<code>
0: PUSH 10
1: STOR AX
2: PUSH 1
3: SUB
4: JNZ 2
5: RSTOR AX
</code>
</pre>
<p>Now I do <code>JNZ 2</code> instead so that I <b>avoid</b> the <code>01: STOR AX</code> line, that does the loop like before but now the <code>AX</code> register has my starting number. After line <code>4: JNZ 2</code> passes I then use <code>RSTOR AX</code> to get that number back, and the program ends with two numbers on the stack: <code>10</code> and <code>0</code>.</p>
<h2>Other Operations</h2>
<p>You can also use these operations to do other things:</p>
<table class="table">
<thead>
<tr>
<th>OPERATION</th><th>DESCRIPTION</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>CLR</code></td><td>Clears <code>BUTTONS</code>. Good for debugging.</td>
</tr>
<tr>
<td><code>HALT</code></td><td>Stop the computer with a message.</td>
</tr>
</tbody>
</table>
<h2>What About Input and Output?</h2>
<p>Astute readers will notice I have no way to input a number from the world, and output a number (or character) to the screen. That's because I did this whole project in about 3 days while playing video games and I'm not sure how to make a fancy looking retro CRT screen. I'll get to that part eventually.</p>
</div>
</div>
</div>
Loading…
Cancel
Save