home *** CD-ROM | disk | FTP | other *** search
-
-
- The first 8 bytes in the system are vectors to the Cold and Warm
- start entries. You can freely jump to them in code anytime.
- The DPUSH and HPUSH labels are space savers. We jump to them
- in several CODE words when we want to push their contents on the
- Parameter Stack.
- >NEXT is where all the action is. It is the guts of the Forth
- Virtual Machine. It must advance the interpretive pointer held
- in the IP register pair and jump indirect to what it points to.
-
- We define a few macros here to make our life a little easier
- later. Using NEXT as a macro allows us to put it inline later.
-
- RP Used to hold the depth of the return stack
- NEST The runtime code for : It pushs the current IP onto
- the return stack and sets the IP to point to the parameter
- field of the word being executed.
- EXIT
- Pop an entry off the return stack and place it into the
- Interpretive Pointer. Terminates a Hi Level definition.
- UNNEST Same as exit. Compiled by ; to help decompiling.
- DODOES
- The runtime portion of defining words. First it pushes the
- IP onto the return stack and then it pushes the BODY address
- of the word being executed onto the parameter stack.
- DOCREATE Leave a pointer to its own parameter field on the
- stack. This is also the runtime for variable.
-
- UP Holds a pointer to the current USER area. ( multitasking )
- @USER A subroutine called from code level words that returns
- the contents of a particular user variable.
- !USER A subroutine called from code level words that sets
- the contents of a particular user variable.
-
- DOCONSTANT The run time code for CONSTANT. It takes the
- contents of the parameter field and pushes it onto the stack.
- DOUSER The run time code for USER variables. Places a
- pointer to the current version of this variable on the stack.
- Needed for multitasking.
- (LIT) The runtime code for literals. Pushes the following
- two bytes onto the parameter stack and moves the IP over
- them. It is compiled by the word LITERAL.
-
-
- BRANCH Performs an unconditional branch. Notice that we
- are using absolute addresses insead of relative ones. (fast)
- ?BRANCH Performs a conditional branch. If the top of the
- parameter stack in True, take the branch. If not, skip
- over the branch address which is inline.
-
- LOOP-EXIT is a common routine used by (LOOP) and (+LOOP)
- It is called when the loop has terminated and is exited
- normally.
- (LOOP) the runtime procedure for LOOP. Branches back to
- the beginning of the loop if there are more iterations to
- do. Otherwise it exits. The loop counter is incremented.
- LOOP-BRANCH A common routine needed twice in the 8080
- implementation of (+LOOP).
- (+LOOP)
- Increment the loop counter by the value on the stack and
- decide whether or not to loop again. Due to the wierdness
- of the 8080, you have to stand on your head to determine
- the conditions under which you loop or exit.
-
- (DO) The runtime code compiled by DO. Pushes the inline address
- onto the return stack along with values needed by (LOOP).
- (?DO)
- The runtime code compiled by ?DO. The difference between
- ?DO and DO is that ?DO will not perform any iterations if
- the initial index is equal to the final index.
- BOUNDS
- Given address and length, make it ok for DO ... LOOP.
-
- These are again the TRANSITION versions of the immediate words
- for looping. They compile the correct run time code and then
- Mark and Resolve the various branches.
-
- >NEXT The address of the inner interpreter.
- EXECUTE the word whose code field is on the stack. Very
- useful for passing executable routines to procedures!!!
- PERFORM the word whose code field is stored at the address
- pointed to by the number on the stack. Same as @ EXECUTE
- DO-DEFER The runtime code for deferred words. Fetches the
- code field and executes it.
- DOUSER-DEFER The runtime code for User deferred words. These
- are identical to regular deferred words except that each
- task has its own version.
- GO
- Execute code at the given address.
- NOOP One of the most useful words in Forth. Does nothing.
- PAUSE Used by the Multitasker to switch tasks.
-
- I returns the current loop index. It now requires
- a little more calculation to compute it than in FIG Forth
- but the tradeoff is a much faster (LOOP). The loop index
- is stored on the Return Stack.
- J returns the loop index of the inner loop in
- nested DO .. LOOPs.
- (LEAVE)
- Does an immediate exit of a DO ... LOOP structure. Unlike
- FIG Forth which waits until the next LOOP is executed.
- (?LEAVE)
- Leaves if the flag on the stack is true. Continues if not.
- LEAVE I have to do this to be 83-Standard.
-
- @
- Fetch a 16 bit value from addr.
- !
- Store a 16 bit value at addr.
- C@
- Fetch an 8 bit value from addr.
- C!
- Store an 8 bit value at addr.
-
- CMOVE
- Move a set of bytes from the from address to the to address.
- The number of bytes to be moved is count. The bytes are
- moved from low address to high address, so overlap is
- possible and in fact sometimes desired.
- CMOVE>
- The same as CMOVE above except that bytes are moved in the
- opposite direction, ie from high addresses to low addresses.
-
- SP@
- Return the address of the next entry on the parameter stack
- SP! ( Warning, this is different from FIG Forth )
- Sets the parameter stack pointer to the specified value.
- RP@
- Return the address of the next entry on the return stack.
- RP! ( Warning, this is different from FIG Forth )
- Sets the return stack pointer to the specified value.
-
- DROP
- Throw away the top element of the stack.
- DUP
- Duplicate the top element of the stack.
- SWAP
- Exchange the top two elements on the stack.
- OVER
- Copy the second element to the top.
-
- TUCK
- Tuck the first element under the second one.
- NIP
- Drop the second element from the stack.
- ROT
- Rotate the top three element, bringing the third to the top.
- -ROT
- The inverse of ROT. Rotates the top element to third place.
- FLIP
- Exhange the hi and low halves of a word.
- ?DUP
- Duplicate the top of the stack if it is non-zero.
-
- R>
- Pops a value off of the return stack and pushes it onto the
- parameter stack. It is dangerous to use this randomly!
- >R
- Pops a value off of the parameter stack and pushes it onto
- return stack. It is dangerous to use this randomly!
- R@
- Copies the value on the return stack to the parameter stack.
- PICK Reaches into the stack and grabs an element, copying it
- to the top of the stack. For example, if the stack has 1 2 3
- Then 0 PICK is 3, 1 PICK is 2, and 2 PICK is 1.
- ROLL
- Similar to SHAKE and RATTLE. Should be avoided.
- 1 ROLL is SWAP, 2 ROLL is ROT, etc.
- ROLL can be useful, but it is slow.
- AND
- Returns the bitwise AND of n1 and n2 on the stack.
-
- OR
- Returns the bitwise OR of n1 and n2 on the stack.
-
- XOR
- Returns the bitwise Exclusive Or of n1 and n2 on the stack.
-
- NOT
- Does a ones complement of the top. Equivalent to -1 XOR.
-
- TRUE FALSE Constants for clarity.
- YES Push a true flag on the stack and jump to next
- NO Push a false flag on the stack and jump to next
- CSET Set the contents of addr so that the bits that are 1 in n
- are also 1 in addr. Equivalent to DUP C@ ROT OR SWAP C!
- CRESET
- Set the contents of addr so the the bits that are 1 in n
- are zero in addr. Equivalent to DUP C@ ROT NOT AND SWAP C!
- CTOGGLE Flip the bits in addr by the value n. Equivalent to
- DUP C@ ROT XOR SWAP C!
- ON
- Set the contents of addr to TRUE
- OFF
- Set the contents of addr to FALSE
-
- +
- Add the top two numbers on the stack and return the result.
- NEGATE
- Turn the number into its negative. A twos complement op.
- -
- Subtracts n2 from n1 leaving the result on the stack.
-
- ABS
- Return the absolute value of the 16 bit integer on the stack
- +!
- Increment the value at addr by n. This is equivalent to
- the following: DUP @ ROT + SWAP ! but much faster.
- 0 1 Frequently used constants
- 2 3 Are faster and more code efficient.
-
- 2*
- Double the number on the Stack.
- 2/
- Shift the number on the stack right one bit. Equivalent to
- division by 2 for positive numbers.
- U2/
- 16 bit logical right shift.
-
- 8*
- Multiply the top of the stack by 8.
-
- 1+ Increment the top of the stack by one.
- 2+ Increment the top of the stack by two.
- 1- Decrement the top of the stack by one.
- 2- Decrement the top of the stack by two.
- You could write a whole book about multiplication and division,
- and in fact Knuth did. Suffice it to say that UM* is the basic
- multiplication primitive in Forth. It takes two unsigned 16 bit
- integers and returns an unsigned 32 bit result. All other
- multiplication functions are derived from this primitive one.
-
- It probably isn't particularly fast or elegant, but that is
- because I never liked arithmetic and I stole this implementation
- from FIG Forth anyway.
-
- U*D is a synonym for UM*
-
-
- These are various subroutines used by the division primitive in
- Forth, namely U/. Again I must give credit for them to FIG
- Forth, since if I can't even understand multiply,
- divide would be completely hopeless.
-
- UM/MOD
- This is the division primitive in Forth. All other division
- operations are derived from it. It takes a double number,
- d1, and divides by by a single number n1. It leaves a
- remainder and a quotient on the stack. For a clearer
- understanding of arithmetic consult Knuth Volume 2 on
- Seminumerical Algorithms.
-
- 0=
- Returns True if top is zero, False otherwise.
- 0<
- Returns true if top is negative, ie sign bit is on.
- 0>
- Returns true if top is positive.
- 0<>
- Returns true if the top is non-zero, False otherwise.
- =
- Returns true if the two elements on the stack are equal,
- False otherwise.
- <> Returns true if the two element are not equal, else false.
- ?NEGATE Negate the second element if the top is negative.
-
- U< Compare the top two elements on the stack as unsigned
- integers and return true if the second is less than the
- first. Be sure to use U< whenever comparing addresses, or
- else strange things will happen beyond 32K.
- U> Compare the top two elements on the stack as unsigned
- integers. True if n1 > n2 unsigned.
- < Compare the top two elements on the stack as signed
- integers and return true if n1 < n2.
- > Compare the top two elements on the stack as signed
- integers and return true if n1 > n2.
-
- MIN Return the minimum of n1 and n2
- MAX Return the maximum of n1 and n2
- BETWEEN Return true if min <= n1 <= max, otherwise false.
- WITHIN Return true if min <= n1 < max, otherwise false.
- 2@
- Fetch a 32 bit value from addr.
-
- 2!
- Store a 32 bit value at addr.
-
- 2DROP
- Drop the top two elements of the stack.
- 2DUP
- Duplicate the top two elements of the stack.
- 2SWAP
- Swap the top two pairs of numbers on the stack. You can use
- this operator to swap two 32 bit integers and preserve
- their meaning as double numbers.
- 2OVER
- Copy the second pair of numbers over the top pair. Behaves
- like 2SWAP for 32 bit integers.
- 3DUP Duplicate the top three elements of the stack.
- 4DUP Duplicate the top four elements of the stack.
- 2ROT rotates top three double numbers.
-
- D+
- Add the two double precision numbers on the stack and
- return the result as a double precision number.
-
- DNEGATE
- Same as NEGATE except for double precision numbers.
-
- S>D
- Take a single precision number and make it double precision
- by extending the sign bit to the upper half.
- DABS
- Return the absolute value of the 32 bit integer on the stack
-
- D2*
- 32 bit left shift.
- D2/
- 32 bit arithmetic right shift. Equivalent to divide by 2.
-
- D- Subtract the two double precision numbers.
- ?DNEGATE Negate the double number if the top is negative.
-
- D0= Compare the top double number to zero. True if d = 0
- D= Compare the top two double numbers. True if d1 = d2
- DU< Performs unsigned comparison of two double numbers.
- D< Compare the top two double numbers. True if d1 < d2
- D> Compare the top two double numbers. True if d1 > d2
- DMIN Return the lesser of the top two double numbers.
- DMAX Return the greater of the the top two double numbers.
-
- This does all the arithmetic you could possibly want and even
- more. I can never remember exactly what the order of the
- arguments is for any of these, except maybe * / and MOD, so I
- suggest you just try it when you are in doubt. That is one
- of the nice things about having an interpreter around, you can
- ask it questions anytime and it will tell you the answer.
-
- *D multiplys two singles and leaves a double.
- M/MOD divides a double by a single, leaving a single quotient
- and a single remainder. Division is floored.
- MU/MOD divides a double by a single, leaving a double quotient
- and a single remainder. Division is floored.
-
-
- */ is a particularly useful operator, as it allows you to
- do accurate arithmetic on fractional quantities. Think of
- it as multiplying n1 by the fraction n2/n3. The intermediate
- result is kept to full accuracy. Notice that this is not the
- same as * followed by /. See Starting Forth for more examples.
-