ZX-IDE Tutorial for programming assembler and ZX BASIC

Any discussions related to the creation of new hardware or software for the ZX80 or ZX81
User avatar
PokeMon
Posts: 2264
Joined: Sat Sep 17, 2011 6:48 pm

ZX81 BASIC, variables, LET statement

Post by PokeMon »

The use of the statement LET for assigning variables should be clear in general.
Here an example from the manual:

Code: Select all

            REM VARIABLES TEST
            REM
            LET EGGS=58
            PRINT EGGS
            PRINT EGGS/2
            PRINT COS(EGGS/12)**2
            LET EGGS=61
            PRINT EGGS
            LET MILK=18.5
            PRINT MILK
This allows in conjunction with PRINT to do all calculations, use of mathematical functions and PRINT the result.
This looks like the listing of the ZX81:
tut1.gif
tut1.gif (112.66 KiB) Viewed 11462 times
There is one speciality I didn't know before and I noticed after studying the corresponding chapter of the manual. The ZX81 supports space characters in label names. I didn't find an easy way to solve it and so I abstained from realizing it. I didn't find this very helpful as there is no distinction between the name with or without spaces. By the way you can do as many spaces as much you like at any position in a variables name. The only rule is, that the variable name has to begin with a letter. Take a look at the following listing:

Code: Select all

            LET M12M=0
            LET 'M 3'=1
            PRINT M3
            PRINT 'M 3'
            CLEAR
Here the variable M3 is defined which can be written as M 3 (with space in the middle) as well. So my recommendation is not to use spaces in variable names and I don't know any programming language supporting this feature.
tut2.gif
tut2.gif (111.83 KiB) Viewed 11462 times
It is possible to use space in variable names using declaration in simple apostrophes. This will be interpreted as string but placed in the program code without the markers for a string (quotes). So the ZX-IDE distincts now between strings place in apostrophes and placed in quotes. Only string placed in quotes will generate the quote markers for the ZX81 to recognize a string.

Code: Select all

            REM VARIABLES TEST 3
            REM
            CLEAR
            PRINT "HI THERE.I AM YOUR ZX81."
            LET EGGS=61
            PRINT "THE PRICE OF EGGS IS ";EGGS;" NEW PENCE A DOZEN"
            LET A$="DOUBLE GLOUCESTER"
            PRINT A$
tut3.gif
tut3.gif (111.16 KiB) Viewed 11462 times
User avatar
PokeMon
Posts: 2264
Joined: Sat Sep 17, 2011 6:48 pm

ZX81 BASIC, labels as line numbers (GOTO, etc.)

Post by PokeMon »

The following code shows examples for some new string manipulation functions and evaluation - like LEN, STR$, VAL.

Code: Select all

            REM MISCELLANEOUS
            REM
    .loop:
            PRINT 2*VAL "78.5"
            PRINT LEN STR$(55*30)
            LET X$="17+4"
            PRINT X$;"=";VAL X$
            LET BUTTER=75
            LET YEAST=40
            PRINT BUTTER,YEAST
            LIST #.loop#
            RUN
The most important new feature is the use of labels instead of line numbers. If manual line numbers are not used and let the ZX-IDE number the lines automatically with AUTOLINE step width, they can be referenced as well using labels. The statement LIST #.loop# references the local lable .loop - or more detailed the line number or a BASIC line following the label.
This looks it like when the program is executed: :mrgreen:
tut4.gif
tut4.gif (114.72 KiB) Viewed 11462 times
Any time a line number is needed, the label can be used as alternative. :wink:
Another example with GOTO:

Code: Select all

            REM 'NEW IN TOWN ...'
            REM
    .loop2:
            INPUT A
            PRINT A,SQR A
            GOTO #.loop2#
            LIST
            CONT
tut5.gif
tut5.gif (111.85 KiB) Viewed 11462 times
User avatar
PokeMon
Posts: 2264
Joined: Sat Sep 17, 2011 6:48 pm

ZX81 BASIC, graphic chars, special chars, charset

Post by PokeMon »

The ZX81 has additional graphic chars which are not available in normal charsets of a PC (chapter 11 of manual). To use these characters in programs written or edited in the ZX-IDE a new special prepared font has to be loaded into the system (Sinclair.ttf). The font file is in the main directory of the ZX-IDE and can be installed while clicking on install in the fontviewer (executed with double click on the file) or by manual copy of this file into the windows/fonts directory.
ttfinst.jpg
ttfinst.jpg (42.56 KiB) Viewed 11406 times
After install the charset with name "SinclairZX" is available in the ZX-IDE as well as in other windows applications. All graphic chars or special chars of the ZX81 are available and a few special chars (ASCII extension). In principle chars can be defined of any amount but practically this is limited to only 256 chars with value $00 - $FF if the source has to be saved in simple text files. Additional some areas in the font can not be used or only in a restricted way ($00-$1F and $80-$9F). Due to this reason only a few german special chars are supported (äüöÄÜÖß) as well as § ´ and €. The value is not identical to the ZX charset as the ASCII definitions are to meet too, so the ZX-IDE uses an internal char table to convert these mixed chars into ZX charset when saving a .p file.

Anyway the font SinclairZX can be used in other applications which allow monospaced fonts as OpenOffice, MS Office and many more as this is an offical TTF outline charset. It can be scaled to any size in comparison to bitmapped fonts which have to be available in any desired resolution. The font was created with FontForge using the Consolas charset as base. In this way the look of the source code is a bit different to standard Courier New font and it is displayed a little bit bigger because the graphic chars do not look very well when displayed too small.
fasmgraph.jpg
fasmgraph.jpg (56.69 KiB) Viewed 11406 times
The graphic mode can be switched on and off with ALT+9. If somebody doesn't like this font or if it is too big the graphic mode can be switched off after using the desired graphic chars and continue programming with the standard font. Only the graphic chars are display with other chars as the other font doesn't know about Sinclair chars. If a file is loaded with open file it is automatically checked for existing graphic chars and graphic mode is switched on automatically.

As there can be used multiple text file at the same time in the ZX-IDE the graphic mode can be switched on and off for any editor window explicitly. The graphic chars are choosen with a simple mouse click on the chars displayed in the upper toolbar and inserts them automatically at the current cursor position into the source code. This is quite fast and simple and more easy to handle than as learning complicate keystrokes like for the original ZX81. The chars can be marked in the source code and copied with CTRL-C and CTRL-V at any other position in the source code. Additionally the last used char can be easily inserted with a CTRL-R keystroke (repeat). This way it is quite easy to define masks for the screen in the ZX-IDE.

This is an example how the graphic chars in the original charset and in a standard charset look like (normally you can not see these both views in one source):
fasmgraph2.jpg
fasmgraph2.jpg (30.72 KiB) Viewed 11406 times
User avatar
PokeMon
Posts: 2264
Joined: Sat Sep 17, 2011 6:48 pm

ZX81 BASIC, graphic chars, special chars, charset

Post by PokeMon »

Here a simple program with a few PRINT statements and graphic charachters and the effect what it looks like on a real ZX81.
This way any screen mask can be entered with simple copy & paste and inserting of graphic chars and maybe a keyboard check for input:
graphpgm.gif
graphpgm.gif (46.36 KiB) Viewed 11406 times


And this does it look like when executed in the Eightyone emulator:
graphpgm2.gif
graphpgm2.gif (91.63 KiB) Viewed 11406 times

Here a small program for output of the charset:
Non printable chars will be output either as ? or as a token.

Code: Select all

2000    REM CHARSET
        LET A=0
2100    PRINT CHR$ A;
        LET A=A+1
        IF A<256 THEN GOTO 2100
        STOP
This does it look like ;)
graphpgm3.gif
graphpgm3.gif (104.63 KiB) Viewed 11406 times
This program uses the function CHR$ which gives the char to a value between 0 and 255. The reverse function is CODE and implemented, too.
User avatar
PokeMon
Posts: 2264
Joined: Sat Sep 17, 2011 6:48 pm

ZX81 BASIC, IF-THEN statement, comparison, STOP

Post by PokeMon »

From version 1.71.01g the IF-THEN statement and all comparison operators are supported.
Any condition or comparison expression can be used in the IF part, see chapter 10 of manual.

The official syntax is IF <condition> THEN <command> while command can be any BASIC statement.
The following conditions can be checked:

Code: Select all

=   equal
>   greater as
<   smaller as
>=  greater or equal
<=  smaller or equal
<>  unequal
AND logical and
OR  logical or
NOT invert a value or result

Example program:

Code: Select all

1000    REM NEXT EXAMPLE
        PRINT "NUMBER","BIGGEST SO FAR"
        INPUT A
        LET BIGGEST=A
back:   PRINT A,BIGGEST
        INPUT A

        IF A=BIGGEST THEN PRINT "A=BIGGEST"
        IF A<BIGGEST THEN PRINT "A<BIGGEST"
        IF A>BIGGEST THEN PRINT "A>BIGGEST"
        IF A<=BIGGEST THEN PRINT "A<=BIGGEST"
        IF A>=BIGGEST THEN PRINT "A>=BIGGEST"
        IF A<>BIGGEST THEN PRINT "A<>BIGGEST"
        IF A=1 AND BIGGEST=1 THEN PRINT "A=BIGGEST=1"
        IF A=1 OR BIGGEST=1 THEN PRINT "A=1 OR BIGGEST=1"
        IF NOT A=1 AND NOT BIGGEST=1 THEN PRINT "A<>1 AND BIGGEST<>1"
        IF BIGGEST<A THEN LET BIGGEST=A
        GOTO #back#
        STOP
The STOP command in the last line interrupts or ends the running program. It can be continued using CONT and will be continued on the program line following the STOP line.
User avatar
PokeMon
Posts: 2264
Joined: Sat Sep 17, 2011 6:48 pm

ZX81 BASIC, FOR-NEXT loop, STEP, FAST, SLOW

Post by PokeMon »

The new version supports FOR-NEXT loops as well (see chapter 12).
The syntax is:
FOR <variable>=<start value> TO <end value> STEP <step width>
while the step width is optional and has a default value of 1.

Code: Select all

4100    FOR C=1 TO 5 STEP 3/2
        PRINT C
        NEXT C
        STOP

4200    FOR M=0 TO 6
        FOR N=0 TO M
        PRINT M;":";N;" ";
        NEXT N
        PRINT
        NEXT M
        STOP


In the first example a step width is given with 3/2 (=1.5) and in the second example there are two nested FOR-NEXT loops.
Any floating point value can be used for STEP as well as a variable.
fornext1.gif
fornext1.gif (111.84 KiB) Viewed 11405 times

Last but not least the version 1.71.01g supports the BASIC commands SLOW and FAST.

In FAST mode the screen display is switched off and the program runs faster but without TV picture. In SLOW mode the screen content is generated from the CPU 50 times per second and slows the program executions which is running only during invisible lines at the top and bottom of the screen.

The following program clarifies the different execution speed:

Code: Select all

5000    SLOW
        FOR N=1 TO 64
        PRINT "º";
        IF N=32 THEN FAST
        NEXT N
        GOTO 5000
slowfast.gif
slowfast.gif (97.85 KiB) Viewed 11405 times
User avatar
PokeMon
Posts: 2264
Joined: Sat Sep 17, 2011 6:48 pm

ZX80 BASIC, overview and instruction set implementation

Post by PokeMon »

The ZX80BASIC implementation is finished now.
Especially the charset implementation has been fixed and it is possible to use ZX graphic characters while acitivating (or deactivating) the graphic mode with ALT-9. For additional hints see ZX81 graphic char implementation. To use the ZX graphic chars it is necessary to install the font SinclairZX.ttf (in root of the ZX-IDE package).

Take notice, that ZX80 functions are available in full text implementation with brackets only and that there are no tokens at the keyboard like the ZX81. This doesn't matter for the IDE as this is anyway a simple text editor for source.
The functions are:
CHR$(), STR$(), TL$(), PEEK(), CODE(), RND(), USR(), ABS() - the logical functions AND,OR,NOT are implemented with tokens instead.

Not all syntax rules of ZX80 are validated when compiling. So it is possible to use one-letter-variables in FOR-NEXT loops only. The ZX80 will then throw a syntax error when executing the program if longer names are used. Some instructions are implemented in two different ways/short forms:
RAND, RANDOMISE
CONT,CONTINUE
GOTO, GO TO
GOSUB, GO SUB

Here the list of all other statements implemented:
IF-THEN
CLS
DIM
FOR-NEXT
LET
NEW
REM
RUN
LIST
LOAD
POKE
SAVE
STOP
CLEAR
INPUT
PRINT
RETURN

PS: As there is now a complete release version of ZX-IDE, I will publish the sources of it on the flatassembler board.
http://board.flatassembler.net/topic.php?t=15062
User avatar
marste
Posts: 250
Joined: Sun Aug 10, 2014 9:58 pm
Location: Italy
Contact:

Re: ZX-IDE Tutorial for programming assembler and ZX BASIC

Post by marste »

When I try to run (F8) I get an error from the IDE (than close immediately after):
"The instruction at 0x00427c85 referenced memory at 0x00427c85. The memory could not be written."

Image

Same error if I try "transfer file"...
User avatar
PokeMon
Posts: 2264
Joined: Sat Sep 17, 2011 6:48 pm

Re: ZX-IDE Tutorial for programming assembler and ZX BASIC

Post by PokeMon »

I moved and answered your question here:

viewtopic.php?f=6&t=795&p=15091#p15091
User avatar
PokeMon
Posts: 2264
Joined: Sat Sep 17, 2011 6:48 pm

Z80 Assembler - undocumented opcodes

Post by PokeMon »

The version 1.71.01m.Z80 of ZX-IDE supports now all undocumented opcodes/instructions as they have been researched and published from Sean Young. The latest version 0.91 can be downloaded here:
http://www.myquest.nl/z80undocumented/

Previous versions allowed only the official instructions published from ZILOG. The IDE supports now some new features with read of .p files and disassembling as well and many programs did use undocumented opcodes in the past. So I decided to support all undocumented instructions as well to let the source to be recompiled after maybe some changes.

Mainly the undocumented instructions refer to the lower und higher 8 bit parts of IX and IY in the same way H and L can be used as 8 bit register or 16 bit register HL. As planned from ZILOG IX and IY can and should be used as 16 bit registers only but the decoding logic does allow the use as 8 bit registers as well. The usual naming for the registers are IXH and IXL or IYh and IYl. For these kind of symbols (not labels !) and instructions the ZX-IDE does not distinct between upper and lower case. So IxH and iYl are possible namings as well. Additional a new SHIFT instruction und some new special BIT and rotate instructions are supported. I will come back later to this.

Code: Select all

    0097: [40A0] DD 7C                              LD  A,IXh
    0099: [40A2] DD 7D                              LD  A,IXl
    009B: [40A4] FD 7C                              LD  A,IYH
    009D: [40A6] FD 7D                              LD  A,IYL
                                           
    009F: [40A8] 67                                 LD  H,A
    00A0: [40A9] DD 67                              LD  IXH,A
    00A2: [40AB] DD 60                              LD  IXH,B
    00A4: [40AD] DD 61                              LD  IXH,C
    00A6: [40AF] DD 62                              LD  IXH,D
    00A8: [40B1] DD 63                              LD  IXH,E
                                           
    00AA: [40B3] DD 64                              LD  IXH,IXH
    00AC: [40B5] 65                                 LD  H,L
    00AD: [40B6] DD 65                              LD  IXH,IXL
    00AF: [40B8] DD 6C                              LD  IXL,IXH
    00B1: [40BA] DD 6D                              LD  IXL,IXL
                                           
    00B3: [40BC] FD 64                              LD  IYH,IYH
    00B5: [40BE] FD 65                              LD  IYH,IYL
    00B7: [40C0] FD 6C                              LD  IYL,IYH
    00B9: [40C2] FD 6D                              LD  IYL,IYL
You can see easily the substitution of registers H and L for IXh, IXl, IYh, IYl while adding the prefix DD or FD to the instruction byte. LD H,A equates opcode $67 and LD IXH,A correlate to $DD,$67. Additional to all load instructions all arithmetical and logical instructions can be used as well in all cases, where H and L are supported:

Code: Select all

    00C1: [40CA] DD 8C                              ADC A,IXh
    00C3: [40CC] DD 85                              ADD A,IXl
    00C5: [40CE] FD A4                              AND IYh
    00C7: [40D0] FD BD                              CP IYL
    00C9: [40D2] DD 25                              DEC IXh
    00CB: [40D4] DD 2C                              INC IXl
    00CD: [40D6] FD B4                              OR  IYH
    00CF: [40D8] FD 9D                              SBC A,IYL
    00D1: [40DA] DD 94                              SUB IXh
    00D3: [40DC] FD AD                              XOR IYl
Interesting is the use of IX and IY with displacements and a second register for all bit instructions (SET/RES), shift instructions (SLA,SRA,SRL) and rotation instructions (RL,RLC,RR,RRC). These instructions stores the result in the memory addressed operand (IX+/-n) as well as in one of the 8 bit register A-L. Uncommon is the "dual" notation with a second register.

Code: Select all

    00DB: [40E4] DD CB 03 86                        RES 0,(IX+3)
    00DF: [40E8] DD CB FD 87                        RES 0,(IX-3),A
    00E3: [40EC] DD CB FD 80                        RES 0,(IX-3),B
    00E7: [40F0] DD CB FD 81                        RES 0,(IX-3),C
    00EB: [40F4] DD CB FD 82                        RES 0,(IX-3),D
    00EF: [40F8] DD CB FD 83                        RES 0,(IX-3),E
    00F3: [40FC] DD CB FD 84                        RES 0,(IX-3),H
    00F7: [4100] DD CB FD 85                        RES 0,(IX-3),L
                                           
    00FB: [4104] DD CB 7F C0                        SET 0,(IX+$7F),B
    00FF: [4108] FD CB 80 C7                        SET 0,(IY-128),A
                                           
    0103: [410C] DD CB FF 17                        RL  (IX-1),A
    0107: [4110] FD CB 02 10                        RL  (IY+2),B
    010B: [4114] FD CB 00 01                        RLC (IY+0),C
    010F: [4118] DD CB 40 1D                        RR  (IX+40h),L
    0113: [411C] FD CB 0F 0F                        RRC (IY+0Fh),A
                                           
    0117: [4120] FD CB FE 21                        SLA (IY-2),C
    011B: [4124] DD CB 11 2B                        SRA (IX+17),E
    011F: [4128] FD CB F8 38                        SRL (IY-8h),B
The first RES instruction is the standard use case and stores the result in IX+3. All following instructions do the same (with a different offset) but with a second 8 bit register as well. The result will be stored in both places, the memory and the 8 bit register as a copy of the result. This allows store and easy and fast additional operations. If IX or IY is addressing memory in ROM area, the result is stored in the 8 bit register only as the ROM can not be written to.

There is additional a new shift instruction available, SLL or shift logical left. This is like SLA (shift arithmetic left) but put a 1 in the lowest bit instead of 0 like SLA. The new instruction can be used for all typical registers and memory referencing.

Code: Select all

    0129: [4132] CB 37                              SLL A
    012B: [4134] CB 30                              SLL B
    012D: [4136] CB 31                              SLL C
    012F: [4138] CB 32                              SLL D
    0131: [413A] CB 33                              SLL E
    0133: [413C] CB 34                              SLL H
    0135: [413E] CB 35                              SLL L
    0137: [4140] CB 36                              SLL (HL)
    0139: [4142] DD CB FC 36                        SLL (IX-4)
    013D: [4146] FD CB 08 36                        SLL (IY+8)
    0141: [414A] DD CB 01 37                        SLL (IX+1),A
    0145: [414E] DD CB 01 30                        SLL (IX+1),B
    0149: [4152] DD CB 01 31                        SLL (IX+1),C
    014D: [4156] FD CB 01 32                        SLL (IY+1),D
    0151: [415A] DD CB 01 33                        SLL (IX+1),E
    0155: [415E] DD CB 01 34                        SLL (IX+1),H
    0159: [4162] DD CB 01 35                        SLL (IX+1),L
There are 2 new I/O instructions. IN F,(C) reads data from port (C) but does not store the value but sets all flags like all other I/O instructions depending on the read data. This is the reason to use the acronym IN F,(C). So the flags can be set/tested without destroying any registers contents. There is a second interesting I/O instruction, OUT (C),0 which puts out a zero byte ($00) to the port addressed by register C. This saves the other 8 bit register contents as well.

Code: Select all

    0163: [416C] ED 78                              IN  A,(C)
    0165: [416E] ED 70                              IN  F,(C)
    0167: [4170] ED 79                              OUT (C),A
    0169: [4172] ED 71                              OUT (C),0
Flags changed with any IN instruction:
S is set if input data is negative; reset otherwise
Z is set if input data is zero; reset otherwise
H is reset
P/V is set if parity is even; reset otherwise
N is reset
C is not affected
Finally there are 2 control directives to allow or denie the undocumented instructions during assembling. Z80LOOSE allows the additional instructions while Z80STRICT will throw an error message when these instructions are used. Default at start of assembly is Z80LOOSE. These control directives can be used many times during assembly to allow or restrict these instructions for different assembly parts.

Code: Select all

                                                    Z80strict
    0171: [417A] CE 63                              ADC A,99
    0173: [417C] 8F                                 ADC A,A
    0174: [417D] 8E                                 ADC A,(HL)
    0175: [417E] DD 8E 01                           ADC A,(IX+1)
    0178: [4181] FD 8E FF                           ADC A,(IY-1)
                                                    Z80loose
    017B: [4184] DD 8C                              ADC A,IXh
    017D: [4186] DD 8D                              ADC A,IXl
    017F: [4188] FD 8C                              ADC A,IYh
    0181: [418A] FD 8D                              ADC A,IYL
Post Reply