home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
forth
/
compiler
/
love
/
chap14.doc
< prev
next >
Wrap
Text File
|
1993-04-11
|
13KB
|
315 lines
Chapter14 L.O.V.E. FORTH
14.0 RPN Assembler
-------------
This is a classic Forth assembler that utilizes RPN syntax.
During assembly, the arguments and opcodes are executed to produce
instructions which are added to the code segment. Those who prefer normal
assembler syntax should use the newer third party assembler facility. This
RPN assembler is included only for older code, or code appearing on
screens.
Though this assembler is large, this penalty is minimized by
including it as a virtual vocabulary. When the interpreter encounters
either the word CODE or ;CODE, the assembler will be called into
upper memory and the assembling of code will start. When no longer needed,
it can be removed by the word FORGET-SYS. It is automatically removed by
SAVE" or any word that calls another virtual subsystem.
It is assumed that the user has access to an 8086/8088 handbook
such as: "iAPX 86,88 User's Manual" by Intel Corporation or "THE 8086 BOOK
includes the 8088" by R.Rector and G.Alexy, OSBORNE/McGraw-Hill (though the
latter has many errors).
14.1 Using the RPN assembler
-----------------------
Normally the external assembler/linker is provided for assembling
code. In order for the RPN assembler to be used, it must be loaded in. The
source code is provided for this. Type the following:
INCLUDE" LOADRASM.TXT" (enter)
To make the change permanent, simply save the forth system with
SAVE" filename.EXE"
14.2 Format for Code Words
---------------------
Assembling is initiated by either CODE or ;CODE and
terminated by C; (or its alias END-CODE ). The exit point(s) in a code
NEXT-JMP assembles the following in-line code:
WORD LODS BX, AX MOV WORD [BX] JMP
The following are examples of usage:
CODE U/MOD BX POP DX POP AX POP DX, BX CMP
IFU< BX DIV DX PUSH APUSH-JMP
THEN AX, # -1 MOV AX PUSH APUSH-JMP C;
: CONSTANT CREATE: TS:,
;CODE
2 [BX] PUSH NEXT-JMP C;
14.3 Logical Operators
-----------------
Logical operators have been added to the Assembler to simplify
writing and reading the assembly code. They also obviate labels and
forward referencing. The logical test words can be used after any
operation code, that causes the appropriate status flags to be set or
cleared; i.e. CMP CMPS OR ADD SUB etc.
With the exception of REPEAT and AGAIN , which assemble
unconditional signed relative two-byte jumps, these logical operators
assemble one-byte jumps. The assembler will detect an attempt to assemble
an out-of-range jump, and will print an appropriate error message, and
stop assembling.
DO .. LEAVE .. LOOP. This construct differs from the high-level
FORTH construct in that only one argument is used. The CX register must
contain the count upon reaching LOOP. The LEAVE operation will set the
CX register to 1 which is first decremented upon reaching LOOP; then, an
exit from the LOOP is made if the CX register is 0. If the CX
register is not 0 upon reaching LOOP, the program counter will be set to
the instruction just after DO. The count placed in the CX register can
vary from 1 to FFFF (65535 decimal). The following is a simple
illustration of usage:
( starting at addr, searches n bytes for char)
( addr n char --- addr -1 or 0 )
CODE CHARSRCH
AX POP CX POP DX, DI MOV DI POP
DO SCAS
IF= DI DEC DI PUSH DI, DX MOV AX, # -1 MOV APUSH-JMP
THEN
LOOP CX PUSH DI, DX MOV NEXT-JMP C;
The sequence: IF=
IF<
IF0<
IFU< ... ELSE ... THEN
will calculate the relative one-byte jumps and assemble the appropriate
code, ie. JNZ JNL JNB or JMP . The IF operators can be used
after any operation that sets the appropriate flags. (Note that
AX, AX OR has the same effect as AX, # 0 CMP but requires one less cycle).
If the logical test is immediately followed by the word 'non'
('not' was not used to avoid conflict with the NOT op code), the test is
negated. For example, AX, BX CMP IF= non ... would perform the operation
following IF= if the AX and the BX registers were not equal.
The following are examples of usage.
CODE MAX AX POP BX POP AX, BX CMP
IF< BX PUSH ELSE AX PUSH THEN NEXT-JMP C;
CODE U< CX POP BX POP AX, AX XOR BX, CX CMP
IFU< AX DEC THEN APUSH-JMP C;
CODE ABS AX POP AX, AX OR
IF0< AX NEG THEN APUSH-JMP C;
CODE DIGIT DX POP BX POP AX, AX XOR BL, # 48 SUB
IF< non BL, # 10 CMP
IF< non BL, # 7 CMP
IF< APUSH-JMP THEN
THEN BL, DL CMP
IF< AX DEC DX, DX XOR DL, BL MOV DX PUSH
THEN
THEN APUSH-JMP C;
In a similar manner, the following logical sequences will compile
the appropriate offsets and jump codes.
BEGIN .. AGAIN
BEGIN .. UNTIL= (or) UNTIL< (or) UNTILU< (or) UNTIL0<
BEGIN .. WHILE= (or) WHILE< (or) WHILEU< (or) WHILE0< ... REPEAT
Because the operation code word TEST produces a logical result,
that appears to be the reverse of the foregoing conditional branch words, a
separate set of words are provided to replace them, namely: IFTEST
IFNOTEST, WHILETEST, WHILENOTEST. Do not use the word 'non' to
negate these words. For example IFNOTEST is the negative of IFTEST.
The following word from the EDITOR illustrates a combined usage
of these operators. The word <#SPCS?> will determine the number of blank
spaces at the end of a 64 character line on the display. The operation is
performed during retrace cycles.
( L#ADDR X-offset llength -- n )
CODE <#SPCS?>
-2 [BP], DI MOV
CX POP AX POP AX, CX ADD AX, 1 SHL AX DEC
DI POP ES PUSH ES: DX, CRTPORT MOV ES: ES, CRTSEG MOV
DI, AX ADD BX, BX XOR STD
BEGIN DI DEC CX DEC
BEGIN AL, DX IN AL, # 1 TEST UNTILNOTEST CLI
BEGIN AL, DX IN AL, # 1 TEST UNTILTEST AL, # 20 MOV SCAS
IF= BX INC ELSE CX, CX XOR THEN CX, # 0 CMP
UNTIL= CLD STI ES POP BX PUSH
DI, -2 [BP] MOV NEXT-JMP C;
14.4 Assembler Addressing
--------------------
The following nomenclature is used in defining the arguments for
the assembler operation codes:
ac = AX or AL
reg = AX AH AL BX BH BL CX CH CL DX DH DL SI DI BP or SP
mem/reg = any register, a direct memory address,
[BX+SI] [BX+DI] [BP+SI] [BP+DI] [SI] [DI]
[BX] [BP], or any bracketed expression plus a
preceding displacement.
port = a number, 0 through FFFF (hex)
data = a number, 0 through FFFF (hex)
segreg = CS DS ES or SS
size = BYTE or WORD (if unspecified, BYTE is assumed)
n = 0 to FF (hex)
14.5 Assembler operation codes
-------------------------
On the following page are the operation codes that can be assembled
by the assembler, and the required formats for the arguments. Note that
the symbol # followed by a space must precede data. Also, when two
arguments are used, they must be separated by a comma followed by a space.
If a register is the first argument, the comma is part of the register
label, eg:
AX, BX MOV
If the first argument is a number for a port or an address, a space
must precede the comma, eg.
0FE42 , BX MOV.
Where there is a one-byte versus two-byte ambiguity, the default is
one byte. To force a two-byte operation, precede the operation code with
the word WORD eg.
WORD [BX] NEG.
Note that when using addresses with JMPs and CALLs the best
size offset (8 or 16 bit) is selected by the assembler. To specify
intersegment JMPs, CALLs +RETs and RETs the prefix FAR is used.
For example:
to perform an intersegment indirect branch, the following sequence
is used:
FAR [BX] JMP
When FAR is not used an intrasegment branch is assumed.
Segment overrides are specified by placing CS: DS: ES: or SS:
in front of the operation they are to modify.
Before exiting from a code word via NEXT-JMP you must restore the
following registers to the values they had upon entry to the routine:
SI, DI
CS, DS, SS, ES
The flags DF, IM must both be restored with the instructions:
STI and CLD.
The following registers must not have unreasonable changes:
SP, BP
For more information on register usage see the implementation notes.
14.6 Assembler LABELs
----------------
In order to create branching or other labels within a code word,
the declaration LABEL can be used. This creates a CONSTANT based on
the current code segment dictionary pointer. This can be refered to in
high-level Forth. This relies on the L.O.V.E. Forth characteristic, that
CONSTANTS only add code to the thread and head segments.
Example:
CODE S>D ( signed conversion ( n -- d )
AX POP CWD
LABEL DXAX-PUSH ( push dx and ax )
DX PUSH AX PUSH NEXT-JMP C;
CODE D2* ( double double ( d-- d)
AX POP DX POP DX, 1 SHL AX, 1 ROL DXAX-PUSH JMP C;
14.7 Operation Codes
---------------
AAA AAD AAM
AAS
ac, # data ADC mem/reg, # data ADC * mem/reg, mem/reg ADC
ac, # data ADD mem/reg, # data ADD * mem/reg, mem/reg ADD
ac, # data AND mem/reg, # data AND * mem/reg, mem/reg AND
address CALL mem/reg CALL CBW
CLC CLD CLI
CMC
ac, # data CMP mem/reg, # data CMP * mem/reg, mem/reg CMP
size CMPS CWD DAA
DAS reg DEC mem/reg DEC *
mem/reg DIV * HLT mem/reg IDIV *
mem/reg IMUL * ac, DX IN ac, port IN
reg INC mem/reg INC * n INT
INTO IRET
address JA address JAE address JB
address JBE address JCXZ address JE
address JB address JGE address JL
address JLE address JMP mem/reg JMP
address JNA address JNAE address JNB
address JNBE address JNE address JNG
address JNGE address JNL address JNLE
address JNO address JNP address JNS
address JNZ address JO address JP
address JPE address JPO address JS
address JZ LAHF
reg, mem/reg LDS reg, mem/reg LES reg, mem/reg LEA
LOCK size LODS address LOOP
address LOOPNE address LOOPNZ address LOOPZ
reg, # data MOV mem/reg, # data MOV * mem/reg, mem/reg MOV
ac, address MOV segreg, mem/reg MOV mem/reg, segreg MOV
address , ac MOV size MOVS mem/reg MUL *
mem/reg NEG * NOP mem/reg NOT *
ac, # data OR mem/reg, # data OR * mem/reg, mem/reg OR
DX, ac OUT port , ac OUT
reg POP mem/reg POP segreg (not CS) POP
POPF PUSHF
reg PUSH mem/reg PUSH segreg PUSH
mem/reg, 1 RCL * mem/reg, CL RCL *
mem/reg, 1 RCR * mem/reg, CL RCR *
REP REPE REPNE
REPNZ REPZ RET
mem/reg, 1 ROL * mem/reg, CL ROL *
mem/reg, 1 ROR * mem/reg, CL ROR *
SAHF
mem/reg, 1 SAL * mem/reg, CL SAL *
mem/reg, 1 SAR * mem/reg, CL SAR *
ac, # data SBB mem/reg, # data SBB * mem/reg, mem/reg SBB
size SCAS
mem/reg, 1 SHL * mem/reg, CL SHL *
mem/reg, 1 SHR * mem/reg, CL SHR *
STC STD STI
size STOS
ac, # data SUB mem/reg, # data SUB * mem/reg, mem/reg SUB
ac, # data TEST mem/reg, # data TEST * reg, mem/reg TEST
WAIT AX, reg XCHG reg, mem/reg XCHG
XLAT
ac, # data XOR mem/reg, # data XOR * mem/reg, mem/reg XOR
n +RET
* these operations require a size BYTE, WORD when the operand is
a memory location(s).