Category: programming


TinyELF delay timer

Even this slow old architecture is actually still really quick.  You’ll often need to burn off some clock cycles between operations just so you can see the output.  Here is a little subroutine I wrote for the 1802 that is adjustable and can be shoehorned into code you may have already written.  You can hook it write into many of the early programs in Tom Pittman’s book “A Short Course in Programming“.  Pretty much anything that has you pushing the “I” key for it to move forward.

0020    F81F    LDI The second byte determines the delay amount

0022    B4        PHI R4 Puts the delay counter into R4

0023    32XX   BZ XX Branch if D=0, second byte directs back.

0025    94        GHI R4 Puts the counter from R4 into D for comparison

0026    24        DEC R4 Decrements R4 by one

0027    3020   BR XX Branches back to check if D is zero.

Here is an example where I have hooked the delay back into my hex counter program so that you don’t have to push “I” for the counter to increment.  I have left the old code structure in tact so you can see the differences.  I also changed the counter location in memory to 0030 but this is arbitrary.

TinyELF Hex autocounter

0000   6400  OUT 4    clear hex display
0002   90       GHI R0  zero the accumulator
0003   B2       PHI R2   Set hi byte to zero
0004   B3       PHI R3   Set hi byte to zero
0005   A3       PLO R3  Set lo byte to zero
0006   F830  LDI         Set D to 30
0008   A2      PLO R2  Set R2 to 30
0009 52         STR Clear 0030 byte
000A   E2      SEX R2  Set X to R2
000B   3020 BR           Instead of waiting for “I”, branch to delay
000D   13       INC R3  Count up
000E   83      GLO R3  Set D to the current count
000F   52       STR R2   Store counter value in 0030
0010   64        OUT 4     Put contents of 0030 on display
0011   22        DEC R2  Keep X pointing at 0030
0012   C4C4   NOP        No need to wait for “i” to be lifted now
0014   300B   BR           Loop back to where wait for “I” was

timer routine;
0020   F85F LDI         The second byte determines the delay amount
0022   B4      PHI R4  Puts the delay counter into R4
0023   320D BZ          Branch when D=0 back to AFTER the branch to 0020
0024   94      GHI R4  Puts the counter from R4 into D for comparison
0025   24      DEC R4  Decrements R4 by one
0027   3023 BR           Branches back to check if D is zero.

TinyELF Hex Counter

I’ve been trying to figure out how to do this nearly since the beginning.  This program represents a huge milestone for me.  It’s the first program that I have created from scratch that does something sort of useful.

It’s amazing how much debugging can go into something so simple as a hex counter.  At first I had to press “I” three times for the counter to start moving upward.  Turns out I had a few commands out of order.  Also, I had a bug where the counter location in memory would not have been properly reset to zero if R2 didn’t have a residual value in it.  Then I had some other misplaced bytes that were confusing me a bit.  I think I have all the kinks worked out now so I’d like to present my hex counter:

0000     6400    OUT    4        clear hex display
0002     90         GHI     R0    zero the accumulator
0003     B2         PHI    R2      Set hi byte to zero
0004     B3         PHI    R3      Set hi byte to zero
0005     A3         PLO    R3     Set lo byte to zero
0006     F820    LDI                Set D to 20
0008     A2        PLO    R2      Set R2 to 20    
0009     52        STR           Clear 0020 byte
000A     E2        SEX    R2      Set X to R2
000B     3F0B   BN4               Wait for “I” to be pushed
000D     13         INC    R3      Count up
000E     83        GLO    R3      Set D to the current count
000F     52         STR    R2      Store counter value in 0020
0010      64        OUT    4         Put contents of 0020 on display
0011      22         DEC  R2        Keep X pointing at 0020
0012     3712     B4                   Wait for “I” to be lifted
0014     300B    BR                  Loop back to wait for “I”

Please excuse the formatting, it’s late.  Anyhow, the program sets itself up by clearing the display, zeroing R3, setting R2 to 20, clearing the byte at memory location 20 and of course setting X to R2.  R2 does double duty in this program.  It points X at byte 0020 in memory and it also tells the STR instruction where to store the value of D.

After the initial setup, we jump into the loop.  First we increment R3(the counter).  Next we stick the counter value in D so we can then store D at memory location 0020.  Then we display the value of 0020 since that is where R2 is pointing.  The 64 OUT 4 instruction incremented the value in R2 so we decrement it immediately so R2 still points at the correct location and doesn’t leak memory.  If you want a good demo of a memory leak, change the value of 0011 from 22 to C4 and then run the program.

I know this program isn’t rocket science but give me a break, I’m still in chapter 4.  Looks like I still have a LONG ways to go to program in “hello world” even…

In Tom Pittman’s book, “A Short Course in Programming“, he introduced the 64 OUT4 instruction in chapter 3 with little explanation other than saying that OUT 4 would output the next byte in memory to the hex display.  This is fine and dandy of course but only if P=X.  I glossed over the P=X part the first time I read chapter 3 however so when he re-introduced OUT 4 in chapter 4, I found myself a bit confused.  In program 4.2, he tries to make sense of this concept.  I am going to take the liberty of recommenting the code to try to make even more sense of it and drive this concept home:

0000 90		GHI 0	.. set D=R0(hi byte), R0=0 after the computer resets
0001 B8		PHI 8      set high byte of R8 to value of D which is zero
0002 80		GLO 0      set D=R0(lo byte), this could JUST as easily be 90
0003 A8		PLO 8      set low byte of R8 to value of D (again, zero)
0004 3F04 WOW:	BN4 *	.. WAIT FOR "I" (This is a good description)
0006 E8		SEX 8      set X register to point at R8
0007 64		OUT 4	.. OUTPUT TO DISPLAY (see more down below)
0008 C4		NOP	.. this byte gets ran so it is critical
0009 3709	B4 *       wait for you to take your finger off "I"
000B 3004	BR WOW	.. REPEAT (start at the wait for "I" statement)

This program as written sends every byte in memory out to the hex display starting at location 0003 in memory.  If you want to start at the beginning of the memory, change 0002 to 90.  This will make sure that R8 is completely zero’d out when you start your count.  One more observation I have is that location 0008 DOES get executed.  If you want to make a slightly more confusing program but save a byte of memory, you can omit the c4 instruction at the location.  Just make sure you change the next branch command to 3708 so it jumps to the correct location.  You can FURTHER save another byte of memory if you omit the 80 GLO command.  Once you’ve GHI’d, you have your D(accumulator) set to zero so why not just PHI and PLO after that without GLOing?

Now for the big explanation.  Obviously the meat of the program happens when X gets pointed at R8.  That tells the OUT4 instruction to output whatever memory location that R8 is pointing at to the hex display.  Usually OUT4 looks at R0 for it’s next byte to display.  It also increments whichever register it’s looking at.  This is why the next byte after 64 usually is skipped and not executed.  Hopefully this makes perfect sense to you by now.  Also, there is nothing special about R8.  Tom just arbitrarily chose R8 out of the stack.  Here is my modified version of Program 4.2 that is smaller, starts at an earlier memory location and uses R2 as the display byte pointer(if that is the proper term…):

0000 90		GHI 0	.. set D=R0(hi byte), R0=0 after the computer resets
0001 B2		PHI 8      set high byte of R2 to value of D which is zero
0002 A2		PLO 8      set low byte of R2 to value of D (again, zero)
0003 3F03 WOW:	BN4 *	.. WAIT FOR "I" (This is a good description)
0005 E2		SEX 8      set X register to point at R2
0006 64		OUT 4	.. display contents of memory location pointed to by X
0007 3707	B4 *       wait for you to take your finger off "I"
000B 3003	BR WOW	.. REPEAT (start at the wait for "I" statement)

In trying to understand the PLO (put low bit in D) and the GLO (get low bit from D) commands, I’m going to write a program that cycles through R1-RF and increments the registers one at a time.  This program is pretty darned boring unless you have the memory contents in full view on the emulator.  Let’s get started:

0000      90      GLO         Set D to zero

0001       A1      PLO         Set R1 to zero

0002      11       INC          Increment R1 (This is the start of where we loop it)

0003      91      GLO         Set D to value of R1

0004      A2     PLO         Set R2 to value of D

0005      92     GLO         Set D to value of R2

0006      A3     PLO         Set R3 to value of D

0007      93     GLO         Set D to value of R3

……      and so on and so on until  …….

0020     30      BR            Unconditional branch to the next byte

0021      02                       Start the program again from 0002

I would suggest running this program in step mode.  This program was designed to HAMMER DOWN the function of these two commands for me.  It’s very illustrative of what these commands do if not a bit repetitive.

I’m starting to wonder how I can write a byte to a specific location in memory now.  Specifically right after a 64 OUT 4 command.  It would be nice to get some of the output devices involved in the fun here.  I have some ideas of how it might work but I’m sweating with anticipation.

Another AHA moment!  The BR 30 (Branch Unconditionally) command is simply changing the value of whatever register that P is pointing at.  The value of P can be changed by the Dr SEP (Set P) command.  It’s starting to all make a bit more sense.  (Pun intended)

TinyELF Emulator for Macintosh OS X

I’ve now hit chapter 4 in Tom Pittman’s “A Short Course in Programming” book that has been graciously posted online for the world to enjoy.  Chapter 4 deals with registers but almost immediately it sends you back to program 2.3 at the end of chapter 2.  I am going to re-comment the code to attempt to make more sense of it.

.. PROGRAM 2.3 — SLOW BLINK
..
0000    91      GHI   Set D(accumulator) to the to highest byte of register 1
0001    CE     LSZ    Skip the next two bytes if D=0
0002    7A     REQ   This turns the Q bit off if D doesn’t equal 0
0003    38     SKP    This skips the next command when D doesn’t equal 0
0004    7B     SEQ    This turns on Q bit if the long skip jumps past the short skip
0005    11      INC     Increment register 1
0006    30     BR      Jump back to the beginning
0007    00                 This is the target of the 30 command

The reason that the high byte is used because the low byte would equal 0 every 256th time the program loops.  This would cause you to never see the Q bit actually blink on the TinyELF emulator because when you cycle the Q bit that quickly, the emulator thinks you are trying to use the speaker that is also attached to the same line.  So when I set my memory address 0000 to 81 instead of 91, I get a super high pitched dog whistle sound coming from my speakers.

The long skip happens 1/256th of the time.  At the point the Q bit gets set to 1.  The program continues to loop and R1 continues to increment 255 more times but the high byte still equal to 0.  These 256 cycles happen so quickly that you barely get to see the Q bit flash before the high byte in R1 changes to to 01 and the short skip jumps past the 7B command.  The program has to loop 65,280 times before you get to see the Q bit blink briefly.

AHA!

TinyELF self-modifying programs

I’ve been delving further into the subject of self-modifying programs on the TinyELF.  Take the program that I showed you in the last posting on the subject for instance:

0000    3F    BN4       Wait for you to press I

0001     00                   3F branches to THIS address if you don’t press “I”, if you do press “I”, it skips to the next address

0002    6c     INP 4    Take whatever is in the IN 4 buffer and put it into the next location in memory, then executes it

0003    00    IDL       It actually doesn’t matter WHAT you put in this spot since the 6C command will change it anyways

0004    00    IDL       after it 6C changes the previous bit, stop (or not depending on what input you send to the program)

Key in the program and then run it.  Type in 6C and then “I”.  So the program fills the memory ENTIRELY with 6C commands.  This is because 6C takes anything sitting in the “In 4” buffer and sticks it in the next byte but that’s not all.  It also RUNS IT!  So when you put in 6C, it still sees 6C in the buffer and then replaces the next byte and then runs that byte which is now 6C, rinse and repeat many, many times.

Now that the memory is filled entirely with 6C’s, re-key the first part of the program:

0000    3F    BN4      Wait for you to press I

0001     00                  3F branches to THIS address if you don’t press “I”, if you do press “I”, it skips to the next address

0002    6c     INP 4    Take whatever is in the IN 4 buffer and put it into the next location in memory

Now type in something like C4 and hit “I”.  If you remember from my last post, C4 is a “no op” command which just tells the computer to skip that byte.   I’ll let you run this yourself to see the output but it’s rather interesting.  See if you can guess what will happen by logical reasoning.

So far, the only command I find that overwrites the program itself is when you enter 6C.  There may be other ways but I’m not an assembly language ninja quite yet.

I’ve been tinkering some more in chapter 3 of Tom Pittman’s Short Course in Programming.  I still think the book is excellent but some of the concepts are starting to become a bit confusing.  For instance, when you take input from the hex keypad via the 6C INP 4 command, the next byte after that one gets modified if your memory protect is not enabled.  It seems this could make input sanitization a difficult task.  It also can make programs run unpredictably if you get a byte or two misplaced.  Of course that is the pitfall with assembly language in the first place.  To explain what I mean, enter in this program:

0000    3F    BN 4      Wait for you to press I

0001     00                  3F branches to THIS address if you don’t press “I”, if you do press “I”, it skips to the next address

0002    6c     INP 4    Take whatever is in the IN 4 buffer and put it into the next location in memory

0003    00    IDL       It actually doesn’t matter WHAT you put in this spot since the 6C command will change it anyways

0004    00    IDL       after it 6C changes the previous bit, stop (or not depending on what input you send to the program)

Now run the program and type in 6C and press the “I”.  I hope you are watching the memory contents window now because that’s crazy.   Re-enter the program and experiment with some other values.

I have absorbed a few other interesting things too.  First one that I like is the C4 NOP command.  No op simply skips to the next byte.  This is good for when you delete a command from memory but you don’t have enough room for a 30 BR LOOP followed by an address byte.

Next thing I like is the 64 OUT 4 command.  That command outputs to the hex display whatever is in the byte following the command.  For instance:

0000     64       OUT 4      This outputs the next byte to the display

0001      FF                         This will be output to the display

0002      00      IDL            Idle until further instructed

There are also other output lines but as far as I can tell, they are attached to anything in the emulator.

TinyELF Emulator for Macintosh OS X

I’ve recently become serious about learning some assembly language.  I’ve always been interested in it but deemed it far too difficult of a task to take on.  It’s usually very mind boggling to look at and sometimes doesn’t make sense at a glance.  Recently I’ve come across a system to practice and learn it relatively easy.  It’s an emulator for OS X called tinyELF.  It’s based on a 1970’s hobbyist computer called the Cosmac ELF which is based on a RCA cpu called the 1802.  The unique thing about this chip is that it has a smallish intruction set of approximately 90 commands and you can enter byte code into it manually via a special loader mode.

The nice advantage of the emulator over the real computer of the 1970’s is that you can look at the memory contents, registers and a step-by-step trace of the instructions being executed.  Also, you can save programs and enter bytes manually into memory thus bypassing the loader.  Another huge advantage over the original Cosmac ELF is that this version features hexadecimal input.  The original elf featured toggle switches and required binary input.

To get started, I HIGHLY suggest reading this book that has been published online for free.  I’m into chapter 3 and so far it’s EXCELLENT.  It’s called A Short Course in Programming by Tom Pittman.  This would be better than me trying to re-explain how to enter programs although it’s much easier than it looks at first glance.

To give you a quick run down, when you start TinyELF, go to the debug menu and check off the Memory Contents, 1802 State and Trace.  These may look daunting at first but they will make sense in a minute.  Next, try out a sample program.  This program will make the R1 register count from 0000 to FFFF and keep rolling over.

0000   11     INC 1            This command increments register 1.

0001    30    BR LOOP    This command loops to the memory location specified in the next byte.

0002   00                          This is the target location for the BR LOOP command to branch off too.

I want to get you programming right away so I’ll tell you exactly what to press to input that program.  On the hex keypad press:

load, 11, I, 30, I, 00, I, Load

As you are doing that sequence, you should see the memory contents filling up.  You will need the 1802 State window open at the very least to see the output of this program.  When you have that window open, hit Run on the hex keypad. Register 2 should be counting up like nuts.  Congratulations, you just keyed in some old school assembly language.  This is very similar to what our forefathers did with punch cards but as I stated before, we have an advantage because we can very easily see the contents of the memory.

I encourage you to read that book that I linked to.  You will learn more than you can imagine about how computers work in a well-explained format.  If you don’t have a Mac, don’t worry, there are 1802 emulators out there for windows as well.  You’ll just have to do a little searching to find one.

This is a nifty trick you can use to impress your friends.  Imagine you have some smallish program that you want to wrap up into a single file for simplicity.  Part of final output perhaps relies on a clever bit of shell scripting and another part relies on a binary of some sort that you need to get the job done.  Here’s a way to wrap it all up in a tidy little package:

#!/bin/sh
grep SRC: $0 | grep -v “grep SRC:” | sed -e s/SRC://g > /tmp/hello.c
gcc -o hello /tmp/hello.c
./hello
exit
SRC: #include <stdio.h>
SRC: int main(int argc, char *argv[])
SRC: {
SRC: printf(“Hello World\n”);
SRC: return 0;
SRC: }

Everything below exit is completely ignored by your shell.  The grep statement goes through the shell script line by line and returns the all the lines starting with “SRC: ” to sed.  Sed uses a simple regex to strip the “SRC: ” off your source code and sends the output to a file in your /tmp directory.  Then the file is compiled and ran.  You could go further and delete the source file out of the /tmp directory if you like or don’t bother.

Hello, world is the most basic of all test programs.  It’s one of the first steps to determine if you have your development environment set up correctly and is also a good first program to learn in any language because it will give you a good idea of the bare minimum requirements to build a program in a given language.

BASIC

Let’s start with Hello, World in basic since that was the first programming language I ever encountered.  The code is very simple:

10 PRINT “Hello, World”

RUN

10 is a line number which is a requirement of old basic compilers.  Generally the lines are numbered  10, 20, 30, etc although they don’t have to be.  Part of the reason for this is so you can later insert other line numbers into your code without renumbering all of your lines of code.  Newer BASIC implementations have sub-routines and other features have have allowed them to ditch the line numbers.  The program is executed from top to bottom so everything in basic has to be in order.  The command RUN at the bottom runs the program and will display your text.  It is not actually part of the program.

Ruby

In Ruby, there are two easy ways to do a hello world program.  I’ll assume you are using a Unix-based machine to try this example.  You’ll need to create a text file called hello.rb with a text editor.  The first way is:

puts ‘Hello, World’

Save your file and type ruby hello.rb at the command prompt.  If all went well, it should print Hello, World and then give you back your command prompt.  I’m assuming that you have installed ruby and it’s in your path.  On a Debian system, it’s easy to install ruby if it’s not already there.  Use a command such as sudo apt-get install ruby.  The other ruby hello world example is:

print(“Hello, World\n”)

C

Hello, World in C is far more complex than any of the other examples.  This is because C is highly structured and not very forgiving.  It also doesn’t have the printf function in the core language so the standard input and output library must be included.  I will also assume you are using a Unix environment for this example.  If you try to run this in a dos/windows environment it will probably fail.  Here is the hello world code in C:

#include <stdio.h>

int main(int argc, char *argv[])
{
printf(“Hello World\n”);
return 0;
}

To run it, you’ll need to put the code in a text file called hello.c.  Then type in gcc hello.c at the command prompt.  This should generate a file called a.out.  At the command prompt, type ./a.out to run the program.  Different compilers and environments may give different results.

Bash

The last example I’ll give is for bash scripting.  Some people would argue that bash is not a programming language but nevertheless it’s a very powerful way to accomplish tasks with other programs and it’s a good way to automate repetitive tasks.  Here is hello world in bash:

#!/bin/sh

echo “Hello, World”

To run this you could simply type the bottom line at the command prompt.  Instead, save it to a file called hello.sh.  Now before you run it, you’ll need to set the executable bit.  Type chmod 755 hello.sh at the command prompt.  Now you can type ./hello.sh to execute the script.

Powered by WordPress. Theme: Motion by 85ideas.