Forth
ZXNet echo conference «code.zx»
From Ivan Mak → To All 20 April 1999
Greetings, All!
The long-awaited subject files go to Igor Gruzdev.
ZX128(1) ZIP 61 747 Fort for ZX-128 with sources
ZX48(1) ZIP 67 554 Fort for ZX-128 with sources
LZ ZIP 15 716 LZ and LZSS compression on fort
4-INT ZIP 17 313 Introduction to the fort
FIG86(1) RAR 37 210 Fort for offtopic
XDEX ZIP 6 731 Fort Ideas (C) Through A.Yu.
FORTH_CP ZIP 23 104 Book "FORT - a language for microprocessors"
Wow! The Protoss are attacking my Zerlings! It's time to get going. Ivan.
- Divorce the scheme, big and small.. ]ZX[
From Kirill Frolov → To All 18 January 2003
================================================================================
* Forwarded by Kirill Frolov (500:812/1.507)
* Area : ZX.SPECTRUM (This is where emulators hang out)
* From : Dima Bystrov, 2:5029/35.26 (16 Jan 03 17:44)
* To : Nick Sevryukov
* Subj : Re: FORTH
================================================================================
Hello Nick!
14 Jan 03 12:58, Nick Sevryukov wrote to Valerij Kozhevnikoff:
VK>> You just need to keep an eye on the stack. And then restore if
VK>> necessary.
VK>> It all depends how often and how it is called and how it should be
VK>> be
VK>> stack all this time.
NS> The main thing is that this program does everything exactly as it should. You are essentially
NS> only rewrote the last jp (hl) command. Read what I used to say
NS> wrote in the explanations of how this should work.
NS> This piece is used quite often and spoils the stack a lot
NS> not recommended! It’s just that it (the stack) is actively used.
NS> ZYZH People, it seems to me that you don’t fully understand how the piece works?! or me
NS> Am I slowing down? this piece is analogous to the piece for x86 processors:NS> lodsw
NS> mov bx, ax
NS> jmp [bx]
NS> Or you can organize it differently, just remember that there is an array with
NS> addresses, sequentially followed by a transition and some pointer
NS> should automatically increase to the next address (see above).
I have a crazier idea :)
have an array not with addresses, but with JP...
to a first approximation it seems that there are only losses, but this is not so
let HL contain the current address (analogue (SP), but without accessing the stack)
Why HL is beneficial will become clear as the text progresses :)
The "interpreter" looks like this:
inc hl,hl,hl
...
jp(hl)
(+JP=18+4+10=32 bars)
(for comparison, call+ret=27 cycles)
It is best to place inc hl,hl,hl at the beginning of the subroutine, in jp (hl) at the end.
if hl is vital, then you can do it
push hl
pop hl
or (simultaneously with popping the parameter from the stack)
ex(sp),hl
pop hl
or (at the same time as pushing the result onto the stack)
push hl
ex(sp),hl
(and other variations)
(the usual method, via call-ret, is quite difficult to use the data stack
inside the subroutine, call-ret plays about 40 bars:
ex(sp),hl:ld(exit+1),hl:pop hl,de...exit:jp 0)
between jp-s you can insert pieces of regular machine code (plain code), but you don’t need toforget to restore hl. for example like this:
ld hl,$+6
jp kudato+3
thus skipping inc hl,hl,hl.
or even
ld l,$+5 ;h turned out to be equal to the old one
jp kudato+3
if we assume that in terms of the execution time of the “interpreter” this method and
classic are approximately not inferior to each other, then here ^^^ on this piece plain
code we win 8 or 11 bars! (the length results in a loss of 2-3 bytes)
at the same time, even the plain construction can be written SIMILARLY (with the same commands)
code;call;goto! (about 18 clock cycles and an average of half a byte are gained)
This is what goto looks like in a normal case:
jp metka
ld hl,kuda
jp(hl)
in fact, this entry will never be needed, because... the case when before goto
is plain code, we discussed it, so let’s consider the case when before goto there is
call:
ld hl,kuda; or ld l
jp metka+3
(not a very logical order, but you can write such a compiler)
here the gain is 8 clock cycles (or 11) and, if you’re lucky, a byte.
Now let's look at the construction of a call with a numeric parameter
in ordinary life this is ld de,param:call metka
and we will have
jp metka
dw param ;you can make many parameters this way
metka
inc hl,hl,hl
ld c,(hl)
inc hl
ld b,(hl)
inc hl
(of course, the option with ld is also possible, but this is rarely profitable)
a conditional jump can be written like this:
jp jpZ
dw where
jpZ
inc hl,hl,hl
jr z,jpZyes
inc hl,hl
jp(hl)
jpZyes
ld a,(hl)
inc hlld h,(hl)
ld l,a
jp(hl)
or, if speed is important,
jp z,kuda
ld hl,$+3 ;or ld l,$+2
where
ld hl,$+3
(here the loss is 5-6 bytes, instead of 2)
loop with precondition:
in normal Asma it is written like this:
<...>
jp while
loop
while
jp cc,loop
<...>
and we will have (if we assume that in <...> there was a call metka, and in there was a call
metka2):
ld hl,while ;or ld l
jp metka+3
loop
ld hl,$+6 ;or ld l,$+5
jp metka2+3
while
jp cc,loop
ld hl,$+6 ;or ld l,$+5
[call metka3+3]
(gain in speed is about 9 cycles for each pass of the cycle, loss in
size 4-5 bytes)
the intermediate result of the calculations must lie in de
for example, an expression with addition:
push de
pop hl
add hl,de
ex de,hl
ld hl,$+3
or with subtraction:
push de
pop hl
or a
sbc hl,de
ex de,hl
ld hl,$+3
or shorter, but slower (you can write any other operation this way):
push de
jp subpp
subpp
inc hl,hl,hl
ex(sp),hl
or a
sbc hl,de
ex de,hl
pop hl
jp(hl)
maybe 2 special calls - jp (ix) and jp (iy), for something very frequent
in general, this is more likely not a fort, but “alternative coding” ;)- Alone Coder [ZX-Guide] [Inferno] [AlCoNews] [ACEdit] [PT] [Chip] [STS]
[ANSI] [8col] [UNRAR]
-+- GoldED/386
+ Origin: There is a line at the store, said T(c)S, and this is a FRACTION (2:5029/35.26)
================================================================================
Press RESET immediately, All!