eForth1  v2.6
eforth_asm.c File Reference

eForth Assembler module More...

#include "eforth_asm.h"
Include dependency graph for eforth_asm.c:

Macros

#define WORDS_ROW_WIDTH   0x44 /** WORDS row width control */
 

Functions

int assemble (U8 *rom)
 
void _dump_rom (U8 *rom, int len)
 

Variables

eForth Assembler module variables
IU PC
 assembler program counter More...
 
U8 R
 assembler return stack index More...
 
U8_byte
 assembler byte array (heap) More...
 
IU _link
 link to previous word More...
 
Compiled Address for Branching
IU DOTQP
 addr of output ops, used by _dotq, _strq, _abortq More...
 

Detailed Description

eForth Assembler module

Forth Macro Assembler Note: TODO: adding Leo Brodie's words

Macro Definition Documentation

◆ WORDS_ROW_WIDTH

#define WORDS_ROW_WIDTH   0x44 /** WORDS row width control */

Function Documentation

◆ assemble()

int assemble ( U8 rom)

eForth Macro Assembler

ROM starting address

< reserved for COLD boot vector

Kernel dictionary (primitive words)

aka doLIST

( u ul uh – f ) check 3rd item within [ul uh)

( udl udh u – ur uq ) unsigned double divided by a single

( u1 u2 – ud ) unsigned double = multiply unsigned singles

( n1 n2 – d ) double = single * single

( n1 n2 – sum c ) add two numbers and carry flag

( n1 n2 n – r q ) multiply n1 n2 div/mod by a single

( n1 n2 – r q ) single devide

( n1 n2 n3 – q ) multiply n1 n2 divide by n3 return quotient

( n – dl dh )

( dl dh – n )

( dl dh – dl' dh' )

( d1l d1h d2l d2h – drl drh dql dqh )

extended words

base of data stack (fixed instead of user var)

address of stack pointer

(TODO: add J)

( f – ) enable/disable debug tracing

( – ) save user variables and dictionary to EEPROM

( – ) restore user variables and dictionary from EERPROM

( n – ) call a C-function vector

Kernel constants

  • 'TIB console input buffer pointer
  • BASE current radix for numeric ops
  • CP, top of dictionary, same as HERE
  • CONTEXT name field of last word
  • LAST, same as CONTEXT
  • 'MODE ('TEVAL - interpreter or compiler)
  • ABORT exception rescue handler (QUIT)
  • HLD char pointer to output buffer
  • SPAN number of character accepted
  • >IN interpreter pointer to next char
  • #TIB number of character received in TIB
  • tmp storage (alternative to return stack)

Console Input and Common words

top of dictionary

use tail of TIB for output

Number Conversions and formatting

( dl dh n – dql dqh u )

handle hex number

handle base > 10

TODO: add >NUMBER

leading with $ (i.e. 0x24)

a FOR..WHILE..NEXT..ELSE..THEN construct =~ for {..break..}

if digit, xBASE, else break to ELSE

whether negative number

Console Output

out-of-range put '_' instead

LF i.e.
actually

Note: DOTQP export to _dotq

( d n – ) fixed width

( u n – ) unsigned fixed size

( u – ) unsigned

( d – ) print, extra space

memory query

TODO: add PAGE

Parsing

( addr len delim – ) delimiter kept tmp, addr in R

if (len) { –len; if (delim==" ") {...} }

a FOR..WHILE..NEXT..THEN construct =~ for {..break..}

for (len)

break to THEN if is char, or next char

no break, (R>, DROP to rm loop counter)

populate A0, i.e. break comes here, rm counter

advance until next space found

a FOR..WHILE..NEXT..ELSE..THEN construct =~ DO..LEAVE..+LOOP

if (char <= space) break to ELSE

no break, if counter < limit loop back to FOR

R>, DROP to rm loop counter

put token length on stack

( b u a – a )

( c – b u )

( – a; <string>) put token at HERE

( c – a; <string)

Dictionary serach

( nfa – cfa )

( a1 a2 n - a1 a2 f ) compare a1, a2 byte-by-byte

*a1++

*a2++

CASE_SENSITIVE

pop off loop counter and pointers

SAME!

TODO: add COMPARE

( a va – cfa nfa, a F ) keep length in tmp

fetch 1st cell

0000 = end of dic

compare 2-byte (uppercased)

CASE_SENSITIVE

miss, try next word

-1, since 1st byte has been compared

compare strings if larger than 2 bytes

get thread field to previous word

word found, get name field

Terminal Input

echo and store new char to TIB

check <CR><LF>

check <TAB>

check BLANK

accquire token from console

loop through input stream

store new char into TIB

check if done

keep token length in #TIB

Text Interpreter

QUERY/TIB/ACCEPT - start the interpreter loop <-------<------.
TOKEN/PARSE - get a space delimited word                      .
EXECUTE - attempt to look up that word in the dictionary       .
  NAME?/find - was the word found?                              ^
  |-Yes:                                                        |
  |   $INTERPRET - are we in compile mode?                      |
  |   |-Yes:                                                    ^
  |   |  \-Is the Word an Immediate word?                       |
  |   |   |-Yes:                                                |
  |   |   |    \- EXECUTE Execute the word -------------------->.
  |   |   |     |                                               |
  |   |   |     \- if (NAME?) EXECU else NUMBQ ---------------->.
  |   |    \-No:                                                |
  |   |        \-Compile the word into the dictionary --------->.
  |    \-No:                                                    |
  |       \- EXECUTE Execute the word ----->------------------->.
   \-No:                                                        ^
      NUMBER? - Can the word be treated as a number?            |
      |-Yes:                                                    |
      | \-Are we in compile mode?                               |
      |  |-Yes:                                                 |
      |  |  |                                                   |
      |  |   \-Compile a literal into the dictionary >--------->.
      |  |                                                      |
      |   \-No:                                                 |
      |     |                                                   |
      |      \-Push the number to the variable stack >--------->.
       \-No:                                                   .
          \-An Error has occurred, prIU out an error message ->

load ABORT vector

@EXECUTE

TODO: add ?STACK

scan dictionary for word

check for compile only word

INTER0 of Dr Ting's

word name not found, check if it is a number

dump stack and ok prompt

fetch token length

fetch operation mode ($INTERPRET or $COMPILE)

execute according to mode

clear TIB, interpreter mode

main query-eval loop

Colon Compiler

store a byte

store a word

create a literal

name found?

is immediate?

execute

a primitive?

XX08 <= this might break

append just the opcode

append colon word address with flag

a number?

append as a literal

add new name field which is already build by PACK$

switch into compiler-mode

TODO: add [']

add word address to dictionary

Debugging Tools

( pfa – nfa )

save BASE, make HEX

get row count

dump one row

:

low-nibble

high-nibble

restore BASE

tmp keeps width

get name length

add to tmp

get LFA

check row width

Optional: Takes ~300 bytes ROM space

display address with colon delimiter ( a – )

display opcode at given address ( a0 op – a1 )

check primitive flag?

colon word - show name

."| or $"| (string)"

a literal?

show the number

(var)v

show jump target

(jump target)j

or a qbran

show jump target

(jump target)?

a bran or donext?

show jump target

(jump target)n

DOES>

(var)*

(does> target)j

skip to defining word

show other opcode#

opcode -> name ( a op – a+1 )

0000 = end of dic

primitive words?

  • check second byte is EXIT

same as our opcode?

print name, done!

link to prev word

?(unknown opcode)

word address

loop until EXIT

disasmble opcode

semi colon

ENABLE_SEE

Control Structures

  • BEGIN...AGAIN, BEGIN... f UNTIL, BEGIN...(once)...f WHILE...(loop)...REPEAT
  • f IF...THEN, f IF...ELSE...THEN
  • n FOR...NEXT, n FOR...(first)... f AFT...(2nd,...)...THEN...(every)...NEXT

TODO: add DO...LOOP, +LOOP, LEAVE

String Literals

find quote in TIB (0x22 is " in ASCII)

advance dic pointer

Defining Words - variable, constant, and comments

change runtime behavior to following code

( ra ca ) para on return stack, offset to defining word

  • the last opEXIT is not needed but nicer

TODO: add POSTPONE

  • CC: Dr. Ting hardcoded here
  • calculate addr of constant

Comments

print til hit ) i.e. 0x29

skip til end of line

Lexicon Bits

enable COMPILE-ONLY flag

enable IMMEDIATE flag

Arduino specific opcodes

( – ud ud ) get current clock (in ms)

( n p – ) set pinMode(p, n=1:OUTPUT, n=0: INPUT)

( h l p – ) set map range to pin

( p – n ) digitalRead(p)

( n p – ) digitialWrite(p, n=1 HIGH, n=0 LOW)

( p – n ) read analog value from pin

( n p – ) set duty cycle % (PWM) to pin

( xt n – ) on timer interrupt calls xt every n ms

( xt p – ) on pin change interrupt calls xt

( f – ) enable/disable timer interrupt

( f – ) enable/disable pin change interrupt

Cold Start address (End of dictionary)

name field of last word

reset vectors

enter the main query loop (QUIT)

current pointer

Boot Vector Setup

◆ _dump_rom()

void _dump_rom ( U8 rom,
int  len 
)

create C array dump for ROM