Assemblers for the ZX80

Any discussions related to the creation of new hardware or software for the ZX80 or ZX81
Moggy
Posts: 3231
Joined: Wed Jun 18, 2008 2:00 pm

Re: Assemblers for the ZX80

Post by Moggy »

Understood Paul many thanks. :D
User avatar
TMD2003
Posts: 149
Joined: Sun Oct 11, 2020 5:39 pm

Re: Assemblers for the ZX80

Post by TMD2003 »

1024MAK wrote: Fri Jun 25, 2021 3:27 pm If there is not much RAM available, a ZX81 will use a collapsed display file (D_FILE). Hence a 1K ZX81 and a 2K TS1000 both use a collapsed display file. But with 4K bytes or more, these machines use a fully expanded display file. See also this post.
This web page is a reasonable summary of the memory map. As you should be able to see, the display file (D_FILE) gets saved to tape as well as the BASIC program and the variables for the program.
Right, that explains it. I knew about the collapsed display file - maybe not in those exact words, I knew at least that only the squares that actually had something printed in them were stored in it while in 1K mode.

The collapsed display file could also explain why my workaround for the ZX80's lack of PRINT AT didn't work, although I'll have to see if I tried that in 1K or more than that. I was poking a couple of system variables to see if it could be done.
1024MAK wrote: Fri Jun 25, 2021 3:27 pm In terms of where and how to store machine code on a ZX80, this chapter is well worth a read (or a re-read if you have already read it).
I've had a quick look over it, found the bits about the OLD ROM and it already looks like the example you've put below with DIM O(5) is the method it says there. It looks good - presumably as variables are saved to tape, they won't be overwritten when the program is loaded, so all the bits of BASIC that put the machine code there in the first place can be erased, leaving just the DIM statement, and there should be a separate warning to type RANDOMISE USR(address) instead of RUN. Am I right?

It's a less stable version of shoving it all in an initial REM, but if there are certain codes it won't accept, I'll stick to the array.

INCIDENTALLY: I found and noted a crude way to check the memory available on a ZX80, seeing as there appears not to be a way to PEEK RAMTOP and STKEND (are these even used on a ZX80?)

Code: Select all

1 REM -  T0
POKE 16431,201 (changes the final zero to an unprintable character which appears as ?)
PRINT USR(16427)
This returns -31713 for a 1K machine and -16353 for 16K.

So I tried to disassemble it and I get:
call c,0 (the printed-from-the-keyboard dash is 220 rather than 18)
add hl,sp
ret

What is going on here? On EightyOne's debugger I can't scroll up and down on the debugger screen and see what's in the ROM at address 0.

ADDENDUM:
Paul wrote: Fri Jun 25, 2021 5:56 pm REM lines can be used without any problem on the ZX80.
You just can't poke whatever you want into them.
The ZX81 has two bytes line length after the line number which makes it possible to jump over the REM line to the next line before continuing to interpret the contents.
The ZX80 does not have the line length and therefore needs to look through every byte of the REM line in order to find the beginning of the next line and can be misled by the contents of a machine code program inside the REM statement which causes crashes.
Is there, anywhere, a complete list of bytes that cannot be poked into a REM statement - so I could still have this option if I made sure none of them were there?

(Say I needed to write LD A,99 and 99 was one of the verboten values, I could work around it with LD A,98 followed by INC A.)

Looking through the chapter Mark mentioned, I see:

76h = 118 = HALT (which is absolutely verboten on a ZX80 and ZX81 anyway, but the value 118 might still be required)
7Eh = 126 = LD A,(HL) ("It is of course the purest of coincidences that 7E happens to be one of the most commonly used machine language instructions of all.") - I suppose LD B/C/D/E,(HL) then LD A,B/C/D/E could be a viable workaround if I'm not too busy with one of those registers.

Any more for any more?
Spectribution: Dr. Jim's Sinclair computing pages.
Features my own programs, modified type-ins, RZXs, character sets & UDGs, and QL type-ins... so far!
User avatar
BarryN
Posts: 151
Joined: Thu Nov 09, 2017 11:34 pm

Re: Assemblers for the ZX80

Post by BarryN »

TMD2003 wrote: Fri Jul 02, 2021 8:16 pm INCIDENTALLY: I found and noted a crude way to check the memory available on a ZX80, seeing as there appears not to be a way to PEEK RAMTOP and STKEND (are these even used on a ZX80?)

Code: Select all

1 REM -  T0
POKE 16431,201 (changes the final zero to an unprintable character which appears as ?)
PRINT USR(16427)
This returns -31713 for a 1K machine and -16353 for 16K.
I tried this on my ZX81 emulation and it didn't work so I guess this only works on a ZX80?
Moggy
Posts: 3231
Joined: Wed Jun 18, 2008 2:00 pm

Re: Assemblers for the ZX80

Post by Moggy »

I wouldn't say 118 is "verboten" on the 81 at least, I have a few self made cipher programs that put this byte into the REM statements I use to store the ciphers and the only thing it does is make the REM unreadable after the 118 byte, then when other bytes are written into the REM in its place it becomes readable again but certainly no crash,program unworkability or whatever so "verboten" seems a tad dramatic I would have thought. ;)
User avatar
mrtinb
Posts: 1906
Joined: Fri Nov 06, 2015 5:44 pm
Location: Denmark
Contact:

Re: Assemblers for the ZX80

Post by mrtinb »

If you read earlier in the thread, you will see mentioned that 118 is different on ZX80, and cannot be included in a REM.
Martin
https://zx.rtin.be
ZX81, Lambda 8300, Commodore 64, Mac G4 Cube
User avatar
1024MAK
Posts: 5101
Joined: Mon Sep 26, 2011 10:56 am
Location: Looking forward to summer in Somerset, UK...

Re: Assemblers for the ZX80

Post by 1024MAK »

TMD2003 wrote: Fri Jul 02, 2021 8:16 pm I've had a quick look over it, found the bits about the OLD ROM and it already looks like the example you've put below with DIM O(5) is the method it says there. It looks good - presumably as variables are saved to tape, they won't be overwritten when the program is loaded, so all the bits of BASIC that put the machine code there in the first place can be erased, leaving just the DIM statement, and there should be a separate warning to type RANDOMISE USR(address) instead of RUN. Am I right?
That’s as I understand it (although I do have a working ZX80 plus a clone, I’ve never actually tried saving any machine code to tape using a real machine or on an emulator, instead I’ve only used an emulator to save via a snapshot :oops:).
Just never use CLEAR or RUN…
TMD2003 wrote: Fri Jul 02, 2021 8:16 pm INCIDENTALLY: I found and noted a crude way to check the memory available on a ZX80, seeing as there appears not to be a way to PEEK RAMTOP and STKEND (are these even used on a ZX80?)

Code: Select all

1 REM -  T0
POKE 16431,201 (changes the final zero to an unprintable character which appears as ?)
PRINT USR(16427)
This returns -31713 for a 1K machine and -16353 for 16K.

So I tried to disassemble it and I get:
call c,0 (the printed-from-the-keyboard dash is 220 rather than 18)
add hl,sp
ret

What is going on here? On EightyOne's debugger I can't scroll up and down on the debugger screen and see what's in the ROM at address 0.
The code at address 0 is the reset / startup code. If this is executed the machine will reset, as after storing values in registers HL and A it jumps to the RAM fill routine. So I don’t think the running program will actually jump to this address. The carry flag must end up set so the CALL is skipped. I think the CALL is just ‘filler’. I’m not sure why this was done though.

Mark
ZX81 Variations
ZX81 Chip Pin-outs
ZX81 Video Transistor Buffer Amp

:!: Standby alert :!:
There are four lights!
Step up to red alert. Sir, are you absolutely sure? It does mean changing the bulb :!:
Looking forward to summer later in the year.
Moggy
Posts: 3231
Joined: Wed Jun 18, 2008 2:00 pm

Re: Assemblers for the ZX80

Post by Moggy »

mrtinb wrote: Fri Jul 02, 2021 10:35 pm If you read earlier in the thread, you will see mentioned that 118 is different on ZX80, and cannot be included in a REM.
I know that but he said Verboten on both machines that's why I never mentioned the ZX80 only the ZX81. ;)
User avatar
1024MAK
Posts: 5101
Joined: Mon Sep 26, 2011 10:56 am
Location: Looking forward to summer in Somerset, UK...

Re: Assemblers for the ZX80

Post by 1024MAK »

This makes more sense to me:

Code: Select all

1 REM 5  T0
POKE 16431,201 (changes the final zero to an unprintable character which appears as ?)
PRINT USR(16427)
Which is:
LD HL,0000
ADD HL,SP
RET

This returns 17396 for a 1K machine and 32756 for a machine with 16K.
Of course, this is only telling you the approximate amount of RAM it thinks the machine has, rather than the actual amount of free RAM…

To get the amount of free RAM, Use:

Code: Select all

1 REM 5  T0
3 PRINT USR(16427)-(PEEK(16396) + 256 * PEEK(16397))
POKE 16431,201 (changes the final zero to an unprintable character which appears as ?)
This gives a result of 918 on a 1K machine and 16278 on a emulated machine with 16K.

Mark
ZX81 Variations
ZX81 Chip Pin-outs
ZX81 Video Transistor Buffer Amp

:!: Standby alert :!:
There are four lights!
Step up to red alert. Sir, are you absolutely sure? It does mean changing the bulb :!:
Looking forward to summer later in the year.
User avatar
marste
Posts: 250
Joined: Sun Aug 10, 2014 9:58 pm
Location: Italy
Contact:

Re: Assemblers for the ZX80

Post by marste »

Paul wrote: Sun Jun 20, 2021 7:34 am A REM line doesn't work on a ZX80 because too many codes make the ZX80 crash when they are LISTed (automatically)
Please have a look at "mastering machine code" for details.
Please consider using ZX-IDE for development or at least some memory expansion while development.
Otherwise only POKE without help of routines will result in enough RAM to be free for program after finishing.
I discovered that writing a double EOL ($76) at the end of a basic line the ZX80 will stop to visualize the rest of the program.

You can use it in the REM but also there is the possibility to write the first line to start (e.g RANDOMIZE USR) and putting the machine code just after it.

I used it in my ZX80 version of 1k Real Chess and the "framework" is available at the address https://sinclairzxworld.com/viewtopic.php?t=2349 (see lines 52-70 of kit_zx1k.asm). Note that might even work without second line number and REM instruction (I've just noted it but do not remember if I tested and/or used).
User avatar
TMD2003
Posts: 149
Joined: Sun Oct 11, 2020 5:39 pm

Re: Assemblers for the ZX80

Post by TMD2003 »

1024MAK wrote: Fri Jun 25, 2021 5:24 pm 9912F765-B019-444D-BC34-F62ED8ED2EFC.jpeg

Mark
Gggggyyyyaaaaaaaaaaaaaah!

I just tested a really simple machine code program, on a Spectrum, to populate 26 consecutive addresses with the alphabet, and then scramble it. It worked. I even made sure it was assembled to 40000+where it would have been had it been ORGed into a REM statement on a ZX80, to make it easier to translate. I deliberately avoided using LD A,(HL) where I needed to (I used C instead - it wasn't doing anything useful - and dumped it into A).

I tried the REM statement version and sure enough, it sent the screen into apoplexy. So I tried the version above, which meant finding out where it was supposed to be stored; I knew the program was 102 bytes, so after DIM O(51), the value I needed was 16575. That's fine, and I tried the routine to populate the right addresses with the alphabet. However, I'd noticed that if I changed that +2 in line 2 to +28, to account for the 26 bytes of the alphabet characters, the new value of A was 16602... when, surely, it should be 16601.

I tried my re-re-assembled program - putting the LD A,(HL) back into it seeing as there was no need to avoid it now - and entered the 127 bytes into the program above, then replaced it with my BASIC listing to test everything was OK...

...and whether I tried RANDOMISE USR (I+26) or (16601)... black screen.

This is doing my head in.

There's no wonder ZX80s are so rare. Those that weren't traded in for a ZX81 at the earliest available opportunity may well have found their flimsy cases smashed to bits against a wall...

I'll bet if I tried the same code on a ZX81 in a REM statement it'd work, no questions asked. (Except that it'll have to be assembled to a different value.)

Is there some way, in an assembler, to point LDs at the value the program is being ORGed to? Say, if it's 32000, it'll start with ORG 32000, and in this program I would need to execute it at USR 32026, and inside the program I also need to point HL at 31999 and 32026. That would have helped no end.
Spectribution: Dr. Jim's Sinclair computing pages.
Features my own programs, modified type-ins, RZXs, character sets & UDGs, and QL type-ins... so far!
Post Reply