From which language is this idiom and forgive my stupid question, but how should I understand it.
But that standard is something that makes it easier to switch to M4 FORTH, so I should stick to it on the other hand if possible.
I came across a web page with UNCONTROLLED FORTH-83 STANDARD where the word 1+ is! and 1-!.
Code: Select all
1+! addr -- "one-plus-store"
Add one to the 16-bit contents at addr.
1-! addr -- "one-minus-store"
Subtract one from the 16-bit contents at addr.
In the "modern" standard there is only the word +!. I didn't see anything in OPTIONAL either. But I would also like -!. Which will answer "swap negate swap -!". So the alternative is 1-!. I originally introduced only +! because it wasn't entirely clear what was to be subtracted from what, but practically you want to have an analogy with the 1-!. It's logical and clear to understand, and it saves code size.
I wrote something about the comparison between C and FORTH and in C I add a boolean value to the address in memory. Just a 16 bit variable stored in memory. But C has TRUE as 1 and FORTH has TRUE as -1, so it is useful to use -!.
By the way, my first entry was something like: "addr @ swap - addr !"
Code: Select all
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH(addr) FETCH SWAP SUB PUSH(addr) STORE'
ld A, [addr] ; 3:13 addr @ swap - ( x1 -- x2 ) x2: [addr]-x1
sub L ; 1:4 addr @ swap -
ld L, A ; 1:4 addr @ swap -
ld A, [1+addr] ; 3:13 addr @ swap -
sbc A, H ; 1:4 addr @ swap -
ld H, A ; 1:4 addr @ swap -
;[5:30] addr ! ( x -- ) addr=addr
ld [addr], HL ; 3:16 addr !
ex DE, HL ; 1:4 addr !
pop DE ; 1:10 addr !
; seconds: 0 ;[15:72]
Code: Select all
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH(addr) ADDSTORE'
ld BC,[addr] ; 4:20 addr +! ( x1 -- x1 ) [addr] += x1
add HL, BC ; 1:11 addr +!
ld [addr], HL ; 3:16 addr +!
ex DE, HL ; 1:4 addr +!
pop DE ; 1:10 addr +! ( a -- )
; seconds: 0 ;[10:61]
Code: Select all
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'NEGATE __ASM PUSH(addr) ADDSTORE'
xor A ; 1:4 negate
sub L ; 1:4 negate
ld L, A ; 1:4 negate
sbc A, H ; 1:4 negate
sub L ; 1:4 negate
ld H, A ; 1:4 negate
ld BC,[addr] ; 4:20 addr +! ( x1 -- x1 ) [addr] += x1
add HL, BC ; 1:11 addr +!
ld [addr], HL ; 3:16 addr +!
ex DE, HL ; 1:4 addr +!
pop DE ; 1:10 addr +! ( a -- )
; seconds: 0 ;[16:85]
Code: Select all
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'PUSH(addr) SUBSTORE'
ld BC, addr ; 3:10 addr -! ( x1 -- x1 ) [addr] -= x1
ld A, [BC] ; 1:7 addr -!
sub L ; 1:4 addr -! lo
ld [BC],A ; 1:7 addr -!
inc BC ; 1:6 addr -!
ld A, [BC] ; 1:7 addr -!
sbc A, H ; 1:4 addr -! hi
ld [BC],A ; 1:7 addr -!
ex DE, HL ; 1:4 addr -!
pop DE ; 1:10 addr -! ( a -- )
; seconds: 0 ;[12:66]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$
I don't really understand the drafters of the standard.
Why only have a quote? It's like in the programming language Karel, who only knows LEFT-SIDE. And you have to program RIGHT-SIDE (RIGHT-FACE I'm not sure what the expression is in English for yelling at the soldiers to turn 90 degrees to the left) via 3x LEFT-SIDE.
Code: Select all
: -! swap negate swap +! ;
PS: In reality, those commands are more complicated to interpret, because the PUSH_SUBSTORE connection breaks down, I have DUP_PUSH_SUBSTORE and DROP. Something like in the physics of small particles... .)
And DROP can easily be connected to the next word that comes up.
If I turn on detailed listing via VERBOSE(1)
Code: Select all
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'VERBOSE(1) PUSH(addr) SUBSTORE'
...new __TOKEN_PUSHS(addr) "{addr}" --> token(1) __TOKEN_PUSHS(addr) "{{addr}}"
...new __TOKEN_SUBSTORE() "-!" --> token(2) __TOKEN_DROP "__dtto"
...check all tokens
...second pass(1) __TOKEN_DUP_PUSH_SUBSTORE(addr) "{addr} -!" --> __TOKEN_DUP_PUSH_SUBSTORE(addr) "{{addr}} -!"
...second pass(2) __TOKEN_DROP() "__dtto" --> same
...check all tokens2
...third pass(1) __TOKEN_DUP_PUSH_SUBSTORE(addr) "{addr} -!" --> __TOKEN_DUP_PUSH_SUBSTORE(addr) "{{addr}} -!"
...third pass(2) __TOKEN_DROP() "__dtto" --> same
...create(1) __TOKEN_DUP_PUSH_SUBSTORE(addr) "{{addr}} -!"
...create(2) __TOKEN_DROP "__dtto"
ld BC, addr ; 3:10 addr -! ( x1 -- x1 ) [addr] -= x1
ld A, [BC] ; 1:7 addr -!
sub L ; 1:4 addr -! lo
ld [BC],A ; 1:7 addr -!
inc BC ; 1:6 addr -!
ld A, [BC] ; 1:7 addr -!
sbc A, H ; 1:4 addr -! hi
ld [BC],A ; 1:7 addr -!
ex DE, HL ; 1:4 addr -!
pop DE ; 1:10 addr -! ( a -- )
; seconds: 0 ;[12:66]
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'VERBOSE(1) PUSH(addr) SUBSTORE PUSH([index])'
...new __TOKEN_PUSHS(addr) "{addr}" --> token(1) __TOKEN_PUSHS(addr) "{{addr}}"
...new __TOKEN_SUBSTORE() "-!" --> token(2) __TOKEN_DROP "__dtto"
...new __TOKEN_PUSHS([index]) "{[index]}" --> token(3) __TOKEN_PUSHS([index]) "{{[index]}}"
...check all tokens
...second pass(1) __TOKEN_DUP_PUSH_SUBSTORE(addr) "{addr} -!" --> __TOKEN_DUP_PUSH_SUBSTORE(addr) "{{addr}} -!"
...second pass(2) __TOKEN_DROP() "__dtto" --> same
...token(2) --> __TOKEN_NOPE
...second pass(3) __TOKEN_PUSHS([index]) "{[index]}" --> __TOKEN_DROP_PUSHS([index]) "{{[index]}}"
...check all tokens2
...third pass(1) __TOKEN_DUP_PUSH_SUBSTORE(addr) "{addr} -!" --> __TOKEN_DUP_PUSH_SUBSTORE(addr) "{{addr}} -!"
...third pass(2) __TOKEN_NOPE() "" --> same
...token(2) --> __TOKEN_NOPE
...third pass(3) __TOKEN_DROP_PUSHS([index]) "{[index]}" --> __TOKEN_DROP_PUSHS([index]) "{{[index]}}"
...create(1) __TOKEN_DUP_PUSH_SUBSTORE(addr) "{{addr}} -!"
...create(2) __TOKEN_NOPE ""
...create(3) __TOKEN_DROP_PUSHS([index]) "{{[index]}}"
ld BC, addr ; 3:10 addr -! ( x1 -- x1 ) [addr] -= x1
ld A, [BC] ; 1:7 addr -!
sub L ; 1:4 addr -! lo
ld [BC],A ; 1:7 addr -!
inc BC ; 1:6 addr -!
ld A, [BC] ; 1:7 addr -!
sbc A, H ; 1:4 addr -! hi
ld [BC],A ; 1:7 addr -!
ld HL,[index] ; 3:16 [index]
; seconds: 0 ;[13:68]