02-08-2015, 05:43 PM
I saw a number of discussions about the 35s check sum calculation so I decided to have a look on it and could figure out the calculation method that I'm now going to explain here. Unfortunately I am not going to tell you why it returns different values on different calculators, I don't know myself and as a matter of fact the simulator and the physical calculator are pretty consistent for me.
Program storage
Each instruction is stored in a block of 3 bytes. The indication LN=xxx is the exact number of bytes consumed by your application. If you divide by three it should return the number of lines. I could decipher most of the OP codes and this 3 bytes size seems to be fairly constant.
On the simulator, if you save the state and check the produced EP file, the programs are stored at the very end of the file, in reverse order (last 3 bytes are the 1st op code).
Magic values
The check sum algorithm is using 6 magic values:
M1:1021h
M2:1231h
M3:3331h
M4:0373h
M5:3730h
M6:4363h
Now let's see how these values are used to calculate the check sum of a very simple program.
Now both my calculator and the simulator tell me
Hexa dump
If you save the state of the simulator and check the end of the file you will find:
01 is apparently a multi purposes bitset of flags
01 is a parameter, here it means 'A'. LBL B would be 01 02 7B
7B is the op code of LBL
3A 00 you can ignore, this is a constant marker for the end of the file.
Let's translate this into 6 binary nibbles
Now we associate a magic number to each nibble in the reverse order
Each nibble has four bits b0, b1, b2, b3
For nibble 1, we calculate V1 = (b0*M1) XOR (2*b1*M1) XOR (4*b2*M1) XOR (8*b3*M1)
V1 = 1021h xor 2*1021h xor 8*1021h = B16Bh
V2 = 1231h xor 2*1231h xor 4*1231h = 7E97h
V3 = 3331h
V4 = 0
V5 = 3730h
V6 = 0
Now we calculate
V1 xor V2 xor V3 xor V4 xor V5 xor V6
CFFCh xor 3331h xor 3730h = CBFDh
Composing multiple instructions
Let's add an instruction after the label
Now the hex dump looks like this:
Using the same method, we find that the SIN instruction produces a checksum of 4F97h.
We sum this with the value found previously for LBL A
4F97h + CBFDh = 11B94h
The 35s is dropping values above 4 digits and this is how we achieve 1B94h
Conclusion
The calculation doesn't yet include strings. The 35s stores EQN is a specific separate memory area while the opcode has a pointer (offset) and I haven't yet checked how they were included; may be this could be the problem because the pointer is part of the opcode and entering EQNs in random order stores strings in random order. I will verify this later.
Apart from that, the calculation is robust and deterministic and so far I always achieved the same results in the simulator and on the physical calculator.
Program storage
Each instruction is stored in a block of 3 bytes. The indication LN=xxx is the exact number of bytes consumed by your application. If you divide by three it should return the number of lines. I could decipher most of the OP codes and this 3 bytes size seems to be fairly constant.
On the simulator, if you save the state and check the produced EP file, the programs are stored at the very end of the file, in reverse order (last 3 bytes are the 1st op code).
Magic values
The check sum algorithm is using 6 magic values:
M1:1021h
M2:1231h
M3:3331h
M4:0373h
M5:3730h
M6:4363h
Now let's see how these values are used to calculate the check sum of a very simple program.
Code:
PRGM TOP
A001 LBL A
Now both my calculator and the simulator tell me
Code:
LBL A
LN=3
CK=CBFD
Hexa dump
If you save the state of the simulator and check the end of the file you will find:
Code:
01 01 7B 3A 00
01 is a parameter, here it means 'A'. LBL B would be 01 02 7B
7B is the op code of LBL
3A 00 you can ignore, this is a constant marker for the end of the file.
Let's translate this into 6 binary nibbles
Code:
0 1 0 1 7 B
0000 0001 0000 0001 0111 1011
Now we associate a magic number to each nibble in the reverse order
Code:
M6 M5 M4 M3 M2 M1
0000 0001 0000 0001 0111 1011
Each nibble has four bits b0, b1, b2, b3
For nibble 1, we calculate V1 = (b0*M1) XOR (2*b1*M1) XOR (4*b2*M1) XOR (8*b3*M1)
V1 = 1021h xor 2*1021h xor 8*1021h = B16Bh
V2 = 1231h xor 2*1231h xor 4*1231h = 7E97h
V3 = 3331h
V4 = 0
V5 = 3730h
V6 = 0
Now we calculate
V1 xor V2 xor V3 xor V4 xor V5 xor V6
CFFCh xor 3331h xor 3730h = CBFDh
Composing multiple instructions
Let's add an instruction after the label
Code:
PRGM TOP
A001 LBL A
A002 SIN
LBL A
LN=6
CK=1B94
Now the hex dump looks like this:
Code:
01 00 43 SIN
01 01 7B LBL A
Using the same method, we find that the SIN instruction produces a checksum of 4F97h.
We sum this with the value found previously for LBL A
4F97h + CBFDh = 11B94h
The 35s is dropping values above 4 digits and this is how we achieve 1B94h
Conclusion
The calculation doesn't yet include strings. The 35s stores EQN is a specific separate memory area while the opcode has a pointer (offset) and I haven't yet checked how they were included; may be this could be the problem because the pointer is part of the opcode and entering EQNs in random order stores strings in random order. I will verify this later.
Apart from that, the calculation is robust and deterministic and so far I always achieved the same results in the simulator and on the physical calculator.