11/30/2016 at 22:58 •
The KIM Uno is capable of displaying 4 hexadecimal digits on the left and two hexadecimal digits on the right. Below it has a hexadecimal keyboard as well as 8 control keys.
This got me thinking. The four digits can represent rotors in an encrypting machine and the two digits on the right can represent the input number and the encrypted version.
The keys below the display can be used to move the rotors. The first row of keys [GO] [ST] [RS] [SST] cannot be used because the ST and RS keys stop a running program and resets the CPU respectively.
The [AD] [DA] [PC] [+] keys have no effect on a running program and can be read. The same situation applies to the row below [C] [D] [E] [F}.
So, we will use [AD]/[C] to increment/decrement the leftmost rotor value. [DA]/[D], [PC]/[E] and [+]/[F] to alter the remaining rotors.
Pressing a 0..9 key will encrypt it and [A] and [B] will be unused for the moment.
12/01/2016 at 04:41 •
Before we get too heavy in the details, let's start by describing how to enter and run a program in the KIM Uno. When you first turn it on, the KIM monitor will run and it will display 0000 00. The monitor will let you examine memory, enter values into memory, run a program and single step a program. The contents of CPU registers and flags can be viewed by accessing special memory locations.
Upon power up, the group of 4 digits on the left is the memory location, the group of 2 digits on the right is the value stored at that address. A key pressed will be interpreted as an address or a value depending on which mode the Kim monitor is on. On power up, reset and stop, the monitor goes into Address mode and keys pressed change the memory location field. To change to data mode, press the [DA] key. A value keyed in will be written to memory. To go back to address mode, press the [AD] key.
An address is entered by keying it with the 0..9 and A..F keys. The address will be shifted left one digit at a time and the memory content field will be updated in real time. To see memory location 200, type 0200. Once all four numbers are keyed, you should see A5 on the right. If you forget to key in the first zero, and another address is shown, just type 0200 again.
If you have my clock program, type [AD]0400 and F8 will appear. Some other values will appear on the right as you type 0400.
The listing below shows a program that will read a key and display its value. The first line specifies the starting memory location. The middle column includes labels and program instructions. The numbers on the right are the opcodes for the program.
This program will call the routines at $1F1F, which displays the values of memory locations $FB $FA on the left 4 digits and $F9 on the right two digits. If the program writes 12 34 56 to $FB, $FA, $F9, the display will show 1234 56.
The next routine called is $1F6A, which reads a key and returns it in the A register. If A is 15 or greater, no key was read. The program stays in a loop defined by the label start, $1F1F is called repeatedly to keep the display alive, otherwise it will be turned off and no digits will be shown at all.
To enter the following program, we will go into address mode and select the starting location, then switch over to data mode and key in the program starting the 20, the first and second lines show the starting location and a symbol called THIRD, those do not result in opcodes, the first program line is JSR $1F1F, which is compiled to 20 1F 1F. To accept one byte and move to the next, press the [+] key. If a mistake is made while entering a memory content, just retype it and press [+] when correct.
For example, if we want to enter 20, but 21 was keyed in instead, just type 20 again and then press [+]
To enter the program below, key in
[AD]100[DA]20+1F+1F+20+6A+1F+C9+ .... B0+F1+
To check your work, press [AD]0100 and repeatedly press the [+] key, The numbers on the right will show in order 20, 1F, 1F, 20 ...
You don't need to enter the whole program in one shot. You can stop at any time, change to address mode, examine memory locations with the [+] key and when you reach an empty memory location, press [DA] and continue entering the program.
I like the listing view because it having the addresses on the left helps keep you on track as you enter the program, when entering the program for the first time, after 20+6A+1F, the Kim Uno will show 0106 on the left and you will know that it is the right place to keep typing C9+
* = $0100
0100 THIRD = 00F9
0100 JSR $1F1F 20 1F 1F
0103 JSR $1F6A 20 6A 1F
0106 CMP #$15 C9 15
0108 BCS START B0 F6
010A STA *THIRD 85 F9
010C SEC 38
010D BCS START B0 F1
This program uses a small trick that allows it to run in any memory location. Conditional jumps like BCS are always relative. The last instruction at 010D to jump back to start is not a JMP START, which will compile to 4C 00 01 and specifies an absolute memory location of 0100 (represented backwards as 00 01). Instead, the jump used was a conditional jump BCS (branch if carry set), which uses a relative number of bytes to jump back. To force the jump to always happen, the carry is set with the SEC (set carry) instruction.
To execute this program, press [AD]0100[GO]
Start with the bottom row and press either 0, 1, 2 or 3.
The same value will be shown in the display. This will continue until you read C,D,E and F.
The AD, DA, PC, + row will also show values.
On the top row, only [GO] reads a value of 13 (hexadecimal).
If you press ST, RS, or SST, the program stops and the screen may blank out. To get a display back press [ST]. To go back into the program, type [AD]0100[GO] and try typing a number. If the number key changes the address field instead of being shown on the left, you are in Single Step mode, press the [SST] key once and the screen will blink. Then press [AD]0100[GO] again and try pressing a number key. It should be shown on the rightmost digits. To stop the program and go back to monitor mode, press the [ST] key.
This program was entered in RAM, powering off the KIM will delete it. To have it permanently available, it must be entered in EEPROM, addresses 0400 thru 07FF. The clock program is stored from 0400 to 0434. You can use 0450 as a starting location for the test program above. To enter it in EEPROM, type [AD]0450[DA]. Blank EEPROM shows up as FF. You will notice that as you type 20, the display blinks and FF is unchanged. This is because read only mode is enabled.
To remove write protection from EEPROM, press and hold the [RS] key for about a second until the display blinks, then press [DA]20 and it will let you write 20 to EEPROM. Pressing the [RS] key drops you back yo address mode. If you do not press [DA] to go back to data mode, you will find yourself changing the memory address instead of the memory value. Simply press [AD]450[DA] to go back to the starting memory location for the program.
To restore the write protection, press and hold [RS] again for about a second until the display blinks again.
And that is a practical primer on using the KIM Uno monitor to examine, change memory and execute a program.
Below are the key values returned when each key is pressed. The ST, RS and SST key cannot be read by code.
13 xx xx xx
10 11 14 12
0C 0D 0E 0F
08 09 0A 0B
04 05 06 07
00 01 02 03
For further reference, see:
The assembler I am using is:
12/01/2016 at 04:54 •
I found that the display routine will have a value in the A register after it returns back to your program. This program displays that value.
* = $0100
0100 THIRD = 00F9
0100 JSR $1F1F 20 1F 1F
0103 STA *THIRD 85 F9
0105 LDA #$00 A9 00
0107 SEC 38
0108 BCS START B0 F6
The values returned are:
78 xx xx xx
7E 7B 6F 54
3C 3B 3A 39
47 46 3E 3D
4B 4A 49 48
4F 4E 4D 4C
They are nice and repeatable, they can be translated to actual key values, but I have not found way to find out when the key is released. The 1F1F routine will keep returning the last key pressed on the A register.even after the key is released. This can be checked because the A register is set to 0 via LDA 00 after displaying it, but the display does not change back to 0 when the key is released.
Without finding a way to check that the key is released, this is not practical yet.
12/04/2016 at 04:52 •
When writing assembly code, the end goal should be very clearly defined. I am trying to write the enigma algorithm for the Z30 machine as a series of additions, subtractions and table lookups.
I already have the rotors written as lookup tables in the format listed below. For example, pin 0 on the right is connected to pin 9 on the left. Pin 1 on the right is connected to pin 6 on the left.
9 6 4 1 8 2 7 0 3 5
The next step is to figure out an algorithm to convert the entry key to a lookup index. The algorithm is shown in the top right corner of the image below and it will turn a key into an index. This index will then be used to lookup the specific output for the rotor selected. In the example listed below, the rotor is showing the value 3 in the window and internally the ring setting is set to 5, the 1 index mark on the inner movable rotor is set to 5 on the visible numbers. If key 7 is pressed, it is equivalent to entering that rotor from pin 6. In the example rotor listed above, this will result in coming out on the left side on pin 7. Repeat for the remaining rotors, go into the reflector and go back through the rotors and the output value (guaranteed to never be 7) will be determined.
12/04/2016 at 13:53 •
The algorithm shown in the table below ends up being 18 bytes of code...
Key In 7 Add Rotor 8 Add 1 9 Over 9? Sub 10 9 Sub RingSt 4 Negative? Add 10 4
;CALL_WITH_A_KEY_TO_ENCODE ;CALL_WITH_X_OFFSET_TO_ROTOR ;REM_SUB_ENRING 0103 ENRING 0103 SEC 38 0104 ADC *ROTORS,X 75 57 0106 CMP #$0A C9 0A 0108 BCC ENRIK1 90 02 010A SBC #$0A E9 0A 010C ENRIK1 010C SEC 38 010D SBC *RINGST,X F5 53 010F BCS ENRIK2 B0 02 0111 ADC #$0A 69 0A 0113 ENRIK2 0113 CLC 18 0114 RTS 60
12/08/2016 at 12:00 •
After a couple of days of struggling to come up with a simple algorithm involving addition, subtraction and one table lookup, the algorithm for one rotor is complete. In comes a 9, out comes a 3. Even better, the steps for the group of instructions at the bottom are the same as the top, just feeding it a fixed input of 0, done with a call to a subroutine, then subjecting the output of another round of (if negative, add 10). Need to investigate byte savings of making a (if negative, add 10) subroutine...
12/10/2016 at 05:05 •
When writing a program for an encryption machine, a paper model is a must. This allows you to see the correct values of all the intermediate steps for a given input.
You can download an excel file here that simulates the signal path through the rotors
The assembly file already implements the signal path through the 3 right rotors. The next step is to write code to go through the reflector and come back the rotors.
12/11/2016 at 15:39 •
Follow the instructions below to get your very own Enigma Z30 machine.
The code above uses SCANDS to display numbers and GETKEY to read the keyboard. Those routines and their dependencies have been listed below and clock in at 150 bytes long. Thus the total byte count for this program when we add the program and the ROM routines it uses is 610 bytes, well below the 1024 limit for this contest.
Title Start End Size AK 1EFE 1F02 4 ONEKEY 1F02 1F19 23 SCANDS 1F1F 1F48 41 CONVD 1F48 1F63 27 GETKEY 1F6A 1F91 39 TABLE 1FE7 1FF7 16 Total 150
12/18/2016 at 01:01 •
There are three keys in the KIM Uno that are not used in the Enigma Z30 program. Those keys are [GO], [A] and [B]. The program has a built in expansion capability. If those keys are pressed, control branches to three vectors, KPUSHA, KPUSHB and KPUSHG. Those addresses contain a jump back to start, but it can be replaced with a jump anywhere. Eventually, control must be restored to the main loop for program execution to continue.
This is the relevand portion of the original code.
CMP #$0A BEQ KPUSHA CMP #$0B BEQ KPUSHB CMP #$13 BEQ KPUSHG JSR MOVROT JMP START ... KPUSHA JMP START KPUSHB JMP START KPUSHG JMP START
We are going to add the functionality to zeroise the encryption keys by resetting them to the default values at the push of a key. This functionality is useful in case an adversary barges into the encryption room, at the push of a key, the current encryption key is destroyed.
When the Z30 program initially starts executing, it checks memory address 0050 for the value 0. If it finds this memory is not initialized, it copies the default encryption key from address DEFVAL in program memory to this RAM address. If we skip the check for 0 and jump to the part of the routine that does the copy, we have effectively implemented a zeroise function. Best of all, we are only changing existing bytes, no code has been added.
And this is the changed code. A couple of lines were changed to use variable TMP01 to allow the timeout routine to clear the last encoded key automatically after [GO] is pushed. The added label adds no code.
INIT CLD LDA #$0 CMP *ENIGVA BNE INITOK ZEROIZ ;REM_ADD_THIS_LABEL LDA #$0B STA *TMP01 ;REM_CHANGE_TO_TMP01 LDX #$0 CPYINI LDA DEFVAL,X STA *ENIGVA,X INX DEC *TMP01 ;REM_CHANGE_TO_TMP01 BNE CPYINI INITOK START ... CMP #$0A BEQ KPUSHA CMP #$0B BEQ KPUSHB CMP #$13 BEQ KPUSHG JSR MOVROT JMP START ... KPUSHA JMP START KPUSHB JMP START KPUSHG JMP ZEROIZ ;REM_CHANGE_TO_ZEROIZ
Test your new functionality by executing the program and changing the rotors with the up/down keys. Then press the [GO] button. The display will return to 4321. Change the rotors again and press a key to encrypt it. While the input and output key are still shown on the right and before they are cleared back to 00, press the [GO] button. They rotors will return to 4321, the last input and output key are still shown, but will be cleared soon by the TIMEOUT routine.
12/18/2016 at 04:01 •
I was looking for a way to make the Excel Paper Model for the Z30 calculate the stepping points so it would be a complete model of the machine. The example shown below is for a rotor with a Ring Setting of 4, the 1 mark on the ring is set to the 4 position on the rotor. When this rotor is showing a 2, it is at its stepping point. The 9 is aligned with the 2 and at position 0 of the Entry Rotor.
This made me realize that I can ask what is the Ring Setting value at position 0 and if it is a 9, then step the next rotor to the right.
This is the old algorithm, it uses an interesting logic to determine the stepping point.
0623 STEPRT 0623 LDX #$00 A2 00 0625 LDY #$03 A0 03 0627 STEPSC 0627 LDA *LRRING,X B5 54 0629 CLC 18 062A ADC #$08 69 08 062C CMP #$0A C9 0A 062E BCC STEPS1 90 02 0630 SBC #$0A E9 0A 0632 STEPS1 0632 CMP *LROTOR,X D5 58 0634 BNE STEPS2 D0 05 0636 LDA #$01 A9 01 0638 JMP STEPDN 4C 3D 06 063B STEPS2 063B LDA #$00 A9 00 063D STEPDN 063D STA *TMP02,X 95 5F 063F INX E8 0640 DEY 88 0641 BNE STEPSC D0 E4 0643 STY *TMP01 84 5E
This is the new algorithm. It calls the ENRING routine with A=0 and Values of X of 1,2 and 3 to see if the three rotors on the right are at the stepping position, indicated by the value of 9.
To get the shorter algorithm to align with 0643, the beginning of the unchanged part, 11 NOP are used.
0623 STEPRT 0623 LDX #$01 A2 01 0625 LDY #$03 A0 03 0627 STEPSC 0627 LDA #$00 A9 00 0629 JSR ENRING 20 67 06 062C CMP #$09 C9 09 062E BEQ STEPDN F0 02 0630 LDA #$00 A9 00 0632 STEPDN 0632 STA *TMP01,X 95 5E 0634 INX E8 0635 DEY 88 0636 BNE STEPSC D0 EF 0638 NOP EA 0639 NOP EA 063A NOP EA 063B NOP EA 063C NOP EA 063D NOP EA 063E NOP EA 063F NOP EA 0640 NOP EA 0641 NOP EA 0642 NOP EA 0643 STY *TMP01 84 5E
In the next release of the program, those 11 NOP will be eliminated.