home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 September
/
Simtel20_Sept92.cdr
/
msdos
/
ddjmag
/
ddj8810.arc
/
80386A.FTH
next >
Wrap
Text File
|
1988-10-31
|
56KB
|
965 lines
SCREE╬ 0
\ 80386 Assembler 10jul88 JBD
\
\ 80386 Assembler
\ Copyright (c) 1988 by John B. Dilworth
\
\ Permission is given to freely use or distribute this program,
\ provided that this entire copyright notice is included on all
\ copies of the source code, or any documentation of the
\ object code. It is released as 'Shareware'; please remit
\ an appropriate amount, based on usage, for registration,
\ extra documentation, updates, etc., to the author at
\ 133 N. Arlington St., Kalamazoo, MI 49007.
\
\ My thanks to Mike Perry and Henry Laxen, whose public-domain
\ F83 Forth system and 8086 Assembler inspired this program.
\
SCREE╬ 1
\ 80386 Assembler Load Screen 10jul88 JBD
: FAF ONLY FORTH ALSO ASSEMBLER ALSO FORTH ; FAF
: CODE CODE FAF ;
\ Above to load on top of F83, 80386 assembler use only.
\ For full use of system, recompile F83 and replace 8086
\ assembler, or set up new Vocabulary for this assembler and
\ redefine CODE etc. to refer to it.
DECIMAL
2 59 THRU CR .( 80386 Assembler loaded.)
EXIT
SCREE╬ 2
\ 80386 Assembler Register, Mode Definitions 10jul88 JBD
OCTAL ( default base)
: REG ( mode reg# -- ) 11 * SWAP 1000 * OR CONSTANT ;
: REGS ( n mode -- ) SWAP 0 DO DUP I REG LOOP DROP ;
10 0 REGS AL CL DL BL AH CH DH BH
10 1 REGS AX CX DX BX SP BP SI DI
10 2 REGS [BX+SI] [BX+DI] [BP+SI] [BP+DI] [SI] [DI] [BP] [BX]
4 2 REGS [SI+BX] [DI+BX] [SI+BP] [DI+BP]
6 3 REGS ES CS SS DS FS GS
3 4 REGS # #) S#)
10 5 REGS EAX ECX EDX EBX ESP EBP ESI EDI
: MD CREATE 1000 * , DOES> @ SWAP 7000 AND = 0<> ;
0 MD R8? 1 MD R16? 2 MD MEM? 3 MD SEG?
5 MD R32? 6 MD MMI32? 7 MD MEM32?
SCREE╬ 3
\ DOUBLE, SIZE32, DOUBLE?, REG32, REGS32, SWD, DWD 10jul88 JBD
VARIABLE DOUBLE VARIABLE SIZE32
: DOUBLE? DOUBLE @ 0<> ; ( test for 32-bit displacement) è
: REG32 ( mode reg# -- )
11 * SWAP 1000 * OR CREATE ,
DOES> @ ( -- constant ) DPL @ -1 = NOT ( double word?)
IF -1 DOUBLE ! -1 DPL ! ELSE 0 DOUBLE ! THEN ;
: REGS32 ( n mode -- )
SWAP 0 DO DUP I REG32 LOOP DROP ;
10 7 REGS32 [EAX] [ECX] [EDX] [EBX] [ESP] [EBP] [ESI] [EDI]
: SWD ( 16-bit disp; use to define single-word vars )
CREATE , DOES> SIZE ON SIZE32 OFF ;
: DWD ( 16-bit disp; use to define double-word vars )
SWAP CREATE , , DOES> SIZE32 ON ;
SCREE╬ 4
\ IREG/S, initializing MMI32 regs [EAX+EBX] etc. 10jul88 JBD
: IREG ( base, loop index -- )
OR 6000 OR CREATE , DOES> @ ( constant)
DPL @ -1 = NOT ( double word?)
IF -1 DOUBLE ! -1 DPL ! ELSE 0 DOUBLE ! THEN ;
: IREGS ( reg# -- ) ( Init's [EAX+EBX] etc. in SIB format )
10 * 10 0 DO DUP I IREG LOOP DROP ;
VARIABLE SPT ( used in prefix tests)
SCREE╬ 5
\ IREGS, initializing MMI32 regs [EAX+EBX] etc. 10jul88 JBD
0 IREGS [EAX+EAX] [ECX+EAX] [EDX+EAX] [EBX+EAX]
[ESP+EAX] [EBP+EAX] [ESI+EAX] [EDI+EAX]
1 IREGS [EAX+ECX] [ECX+ECX] [EDX+ECX] [EBX+ECX]
[ESP+ECX] [EBP+ECX] [ESI+ECX] [EDI+ECX]
2 IREGS [EAX+EDX] [ECX+EDX] [EDX+EDX] [EBX+EDX]
[ESP+EDX] [EBP+EDX] [ESI+EDX] [EDI+EDX]
3 IREGS [EAX+EBX] [ECX+EBX] [EDX+EBX] [EBX+EBX]
[ESP+EBX] [EBP+EBX] [ESI+EBX] [EDI+EBX]
( ESP can't be index register)
5 IREGS [EAX+EBP] [ECX+EBP] [EDX+EBP] [EBX+EBP]
[ESP+EBP] [EBP+EBP] [ESI+EBP] [EDI+EBP]
6 IREGS [EAX+ESI] [ECX+ESI] [EDX+ESI] [EBX+ESI]
[ESP+ESI] [EBP+ESI] [ESI+ESI] [EDI+ESI]
7 IREGS [EAX+EDI] [ECX+EDI] [EDX+EDI] [EBX+EDI]
[ESP+EDI] [EBP+EDI] [ESI+EDI] [EDI+EDI]
SCREE╬ 6
\ SREG, etc. ( Special registers ) 10jul88 JBD
: SREG ( 13-15th bits + regval -- ) CONSTANT ;
HEX 2000 SREG CR0 2012 SREG CR2 201B SREG CR3
4000 SREG DR0 4009 SREG DR1 4012 SREG DR2 è 401B SREG DR3 4036 SREG DR6 403F SREG DR7
8036 SREG TR6 803F SREG TR7
OCTAL
: CTL? 20000 AND 0<> ; ( tests for control, debug, test regs)
: DBG? 40000 AND 0<> ;
: TRG? 100000 AND 0<> ;
: SPL? 160000 AND 0<> ; ( One of bits 13-15 set?)
SCREE╬ 7
\ Constants, Address modes, Immediate data + tests 10jul88 JBD
: D# 4033 -1 DPL ! ; ( 32-bit immed. data)
: D#) 4050 0 DOUBLE ! -1 DPL ! ; ( 32-bit direct mem. disp)
: SD#) 4060 0 DOUBLE ! -1 DPL ! ;
( non-relative 32-bit call/jmp disp)
10000 CONSTANT *1 10100 CONSTANT *2 ( scaling factors)
10200 CONSTANT *4 10300 CONSTANT *8
: #? # = 0<> ;
: D#? D# = 0<> ;
BP CONSTANT RP [BP] CONSTANT [RP] ( RETURN STACK POINTER )
SI CONSTANT IP [SI] CONSTANT [IP] ( INTERPRETER POINTER )
BX CONSTANT W [BX] CONSTANT [W] ( WORKING REGISTER )
SCREE╬ 8
\ Addressing Modes, etc. 10jul88 JBD
: REG? ( n -- f ) DUP 17000 AND 2000 <
IF ( If 8 or 16-bit reg) DROP -1 ELSE R32? THEN ;
: BIG? ( n -- f ) ABS -400 AND 0<> ;
: RLOW ( n1 -- n2 ) 7 AND ;
: RMID ( n1 -- n2 ) 70 AND ;
VARIABLE SIZE SIZE ON
: BYTE ( -- ) SIZE OFF ;
: OP, ( n op -- ) OR C, ;
: ,/C, ( n f -- ) IF , ELSE C, THEN ;
: RR, ( mr1 mr2 -- ) RMID SWAP RLOW OR 300 OP, ;
VARIABLE LOGICAL
: B/L? ( n -- f ) BIG? LOGICAL @ OR ;
SCREE╬ 9
\ Direct or Indirect Memory (Address size) tests 10jul88 JBD
: #)? #) = 0<> ;
: D#)? 4050 = 0<> ;
: SD#)? 4060 = 0<> ;
: U#)? DUP #)? SWAP D#)? OR 0<> ; è
: SIZE32? SIZE32 @ 0<> ;
: *? DUP *1 = 1 PICK *2 = OR 1 PICK *4 = OR ( --reg, flg)
1 PICK *8 = OR 0<> SWAP DROP ;
: UMEM32? DUP MEM32? SWAP MMI32? OR 0<> ;
: UMEM? DUP DUP UMEM32? SWAP MEM?
2 PICK *? OR OR 0<> SWAP DROP ;
: UMEMA? DUP UMEM? SWAP U#)? OR 0<> ; ( Any-memory test)
SCREE╬ 10
\ 32-bit operation words 10jul88 JBD
VARIABLE USE USE OFF
: USE? USE @ 0<> ;
: USE16 USE OFF SIZE32 OFF ; ( 386 default segment types)
: USE32 USE ON SIZE32 ON ;
: WRAP USE? IF ( 32-bit) SIZE32 ON ELSE SIZE32 OFF THEN
SIZE ON ;
( Operand sizes )
: BY ( -- ) BYTE ;
: WD ( -- ) SIZE ON SIZE32 OFF ;
: DW ( -- ) SIZE32 ON ;
: W, ( op mr -- )
DUP R16? 1 AND SWAP R32? 1 AND OR OP, ;
: SIZE, ( op -- op' )
SIZE @ 1 AND SIZE32 @ 1 AND OR OP, ;
SCREE╬ 11
\ MMI32*, ( disp [EAX+EBX] *x cases) 10jul88 JBD
: MMI32*, ( disp mr *x rmid -- ) ( mr of [eax+ebx] form)
DOUBLE? NOT
IF ( test for |--|---|101|) 2 PICK
7 AND 5 = 4 PICK 0= AND ( is it 0 [ebp+reg] case?)
IF ( --disp mr *x rmid) 104 OP, OR C, C,
ELSE ( any other case; mode 0, 1 or 2) 3 PICK BIG?
IF 204 OP, OR C, , 0 ,
ELSE 3 PICK 0= ( mode 0?)
IF ( --disp mr *x rmid) 4 OP, OR C, DROP ( mode 0,no disp)
ELSE 104 OP, OR C, C, ( mode 1, byte disp) THEN THEN THEN
ELSE ( double) ( --disp mr *x rmid) 204 OP, ( --disp mr *x)
OR C, SWAP , , ( mode 2, 32-bit disp) THEN ;
SCREE╬ 12
\ MEM*, MEM32*; MEM32 scaling cases, disp [eax] *x 10jul88 JBD
( disp [EAX] *X cases: must code as [disp32+{scale*index}] )
: MEM32*, ( disp mr *x rmid -- ) ( mr of [eax] form)
4 OP, ( disp mr *x) è SWAP ( disp *x mr) OR ( disp rslt)
5 OP, ( disp)
DOUBLE? IF SWAP , , ELSE , 0 , THEN ;
: MEM*, ( disp mr *x rmid -- )
RMID SWAP 377 AND ( --disp mr rmid *x ) ( 8 bits only)
SWAP 2 PICK ( --disp mr *x rmid mr) MEM32?
IF ROT RMID -ROT ( __disp mr *x rmid) MEM32*,
ELSE ROT 377 AND -ROT MMI32*, THEN ;
SCREE╬ 13
\ MEM#), MEM16, ( all drct mem + 16-bit indrct mem ) 10jul88 JBD
: MEM#), ( disp mr rmid -- ) OVER #) = ( direct mem opnd)
IF RMID 6 OP, DROP , ELSE
OVER D#)? IF RMID 5 OP, DROP SWAP , , THEN THEN ;
: MEM16, ( disp mr rmid -- ) ( Original indirect mem cases)
RMID OVER RLOW OR -ROT [BP] = OVER 0= AND
IF SWAP 100 OP, C, ELSE SWAP OVER BIG?
IF 200 OP, , ELSE OVER 0=
IF C, DROP ELSE 100 OP, C,
THEN THEN THEN ;
SCREE╬ 14
\ MMI32, ( disp [EAX+EBX] cases, MMI32? test) 10jul88 JBD
( Extra SIB byte needed)
: MMI32, ( disp mr rmid -- ) ( mr of [eax+ebx] form)
RMID DOUBLE? NOT
IF ( all non-double-disp cases) OVER ( --disp mr rmid mr)
7 AND 5 = 3 PICK 0= AND ( is it 0 [ebp+reg] case?)
IF ( --disp mr rmid) 104 OP, C, C,
( |01|reg|100|, =[ebp+{scl*indx}+dsp8])
ELSE 2 PICK BIG? ( > 8 bits? If so, mode 2, 32-bit disp)
IF 204 OP, C, , 0 ,
ELSE 2 PICK 0=
IF ( --disp mr rmid) 4 OP, C, DROP ( mode 0, no disp)
ELSE 104 OP, C, C, ( mode 1, byte disp) THEN THEN THEN
ELSE ( double) 204 OP, C, SWAP , , THEN ;
SCREE╬ 15
\ Addressing: MEM32, (disp [EAX] cases, MEM32? test) 10jul88 JBD
: MEM32, ( disp mr mr -- )
RMID OVER RLOW OR DOUBLE? NOT
IF ( all single-disp cases) -ROT ( -- rslt disp opnd)
[EBP] = OVER 0= AND
IF ( --rslt, disp) SWAP 100 OP, C, ( mode 1 with 0 disp)
ELSE SWAP OVER BIG? ( larger than 8 bits?)
IF 200 OP, , 0 , ( 16-bit case)
ELSE OVER 0= è IF ( --disp, rslt) C, DROP ( mode 0, no disp)
ELSE 100 OP, C, ( mode 1, byte disp) THEN THEN THEN
ELSE ( double disp) NIP 200 OP, SWAP , , THEN ;
SCREE╬ 16
\ Addressing: MEM, ( cases satisfying UMEMA? test) 10jul88 JBD
: MEM, ( disp ?op mr mr -- )
OVER U#)? IF MEM#), ELSE
OVER MEM? IF MEM16, ELSE
OVER MEM32? IF MEM32, ELSE
OVER MMI32? IF MMI32, ELSE
MEM*, THEN THEN THEN THEN ;
SCREE╬ 17
\ Segment and Segment Override handling 10jul88 JBD
HEX VARIABLE INTER
: FAR ( -- ) INTER ON ;
: ?FAR ( n1 -- n2 ) INTER @ IF 8 OR THEN INTER OFF ;
VARIABLE SOVROP VARIABLE SOVRFLG SOVRFLG OFF
: SEGOVR ( opcode -- ) CREATE C, DOES>
C@ SOVROP C! SOVRFLG ON ;
2E SEGOVR CS: 3E SEGOVR DS: 26 SEGOVR ES:
36 SEGOVR SS: 64 SEGOVR FS: 65 SEGOVR GS:
: SOVR? SOVRFLG @ 0<> ;
: SEGOVR? SOVR? IF SOVROP C@ C, SOVRFLG OFF THEN ; OCTAL
: SEG16? ( -- f; is it ES,CS,SS or DS?) ( 12MI use)
DUP SEG? IF 40 AND 0= ELSE DROP 0 THEN ;
: SEG32? ( -- f; is it FS or GS?) ( 12MI use)
DUP SEG? IF 40 AND 0<> ELSE DROP 0 THEN ;
SCREE╬ 18
\ Address Prefix handling: APREFX32 etc. 10jul88 JBD
( Handle Adr/Operand-Size 386 Prefixes)
VARIABLE OPSET ( 0 for 1-operand opcodes, 1 for others)
: OPSET? OPSET @ 0<> ;
VARIABLE DUN 0 DUN ! : DUN? DUN @ 0<> ;
: APREFX32 ( ...-...)
SPT @ PICK DUP DUP D#)? SWAP UMEM32? OR SWAP *? OR
IF 1 DUN !
ELSE SPT @ PICK DUP DUP MEM? SWAP #)? OR SWAP S#) = OR
IF 147 C, 1 DUN ! THEN THEN
SPT @ 0= ( move ptr to begn of source opnds)
OPSET? AND
IF ( must be reg ) 1 SPT ! THEN ;
SCREE╬ 19
\ Address Prefix handling: APREFX16 etc. 10jul88 JBDè
: APREFX16 ( ...-...) ( USE16, 32 bit adr. cases)
SPT @ PICK DUP #)? SWAP MEM? OR
IF 1 DUN ! ( no adr-size prefix reqd)
ELSE SPT @ PICK DUP UMEM32? SWAP D#)? OR ( --..flg)
SPT @ 1+ PICK DUP *? SWAP SD#)? OR OR
IF 147 C, 1 DUN ! THEN THEN
SPT @ 0= ( move ptr to begn of sOs opnds)
OPSET? AND
IF ( must be reg) 1 SPT ! THEN ;
SCREE╬ 20
\ Operand Prefix handling: OPREFX32 10jul88 JBD
: OPREFX32 ( ...--...) ( USE32, but 16-bit opnds?)
SPT @ PICK DUP D#? SWAP R32? OR
IF 1 DUN !
ELSE SPT @ PICK DUP R16? SWAP #? OR
IF 146 C, 1 DUN ! THEN THEN
SPT @ 0= ( move ptr to begn of source opnds)
OPSET? AND
IF DUP REG? IF 1 SPT ! THEN
DUP DUP MEM? SWAP #)? OR IF 2 SPT ! THEN
DUP D#)? IF 3 SPT ! THEN
DUP UMEM32? IF DOUBLE? IF 3 SPT ! ELSE 2 SPT ! THEN THEN
DUP *? IF DOUBLE? IF 4 SPT ! ELSE 3 SPT ! THEN THEN
THEN ;
SCREE╬ 21
\ Operand Prefix handling: OPREFX16 10jul88 JBD
: OPREFX16 ( ...--...) ( USE16, but 32 bit operands?)
SPT @ PICK DUP #? SWAP R16? OR
IF 1 DUN ! ( no opnd-size prefix required)
ELSE SPT @ PICK DUP R32? SWAP D#? OR
IF 146 C, 1 DUN ! THEN THEN
SPT @ 0= ( move ptr to begn of source opnds)
OPSET? AND
IF DUP REG? IF 1 SPT ! THEN
DUP DUP MEM? SWAP #)? OR IF 2 SPT ! THEN
DUP D#)? IF 3 SPT ! THEN
DUP UMEM32? IF DOUBLE? IF 3 SPT ! ELSE 2 SPT ! THEN THEN
DUP *? IF DOUBLE? IF 4 SPT ! ELSE 3 SPT ! THEN THEN
THEN ;
SCREE╬ 22
\ Addrs/Operand Prefixes: PREFX, ADRPREFX, OPNDPREFX 10jul88 JBD
: OPNDPREFX ( ..reg -- ..reg ) 0 SPT ! 0 DUN ! USE?
IF OPREFX32 DUN? NOT
IF OPREFX32 DUN? NOT SIZE32? NOT AND
IF 146 C, THEN THEN
ELSE OPREFX16 DUN? NOT è IF OPREFX16 DUN? NOT SIZE32? AND
IF 146 C, THEN THEN THEN ;
: ADRPREFX ( ..Reg -- ..Reg ) 0 SPT ! 0 DUN !
USE? IF APREFX32 DUN? NOT IF APREFX32 THEN
ELSE APREFX16 DUN? NOT IF APREFX16 THEN THEN ;
: PREFX ( ..reg opadr. -- ..reg opadr)
ADRPREFX OPNDPREFX SEGOVR? ;
VARIABLE OP
: OFFPREFX ( ..op -- ..op ) OP C! OPSET OFF PREFX OP C@ ;
: ONPREFX ( ..op -- ..op ) OP C! OPSET ON PREFX OP C@ ;
SCREE╬ 23
\ OPND, OPADR; WMEM, R/M, WR/SM, 10jul88 JBD
VARIABLE OPND VARIABLE OPADR
: WMEM, ( disp mem reg op -- ) OVER W, MEM, ;
: R/M, ( mr reg -- ) OVER REG? IF RR, ELSE MEM, THEN ;
: WR/SM, ( rm reg op -- ) 2 PICK DUP REG?
IF W, RR, ELSE DROP SIZE, MEM, THEN SIZE ON ;
SCREE╬ 24
\ 1MI, 2MI 10jul88 JBD
: 1MI CREATE C, DOES> C@ C, ;
HEX
37 1MI AAA 3F 1MI AAS F8 1MI CLC FC 1MI CLD FA 1MI CLI
F5 1MI CMC 27 1MI DAA 2F 1MI DAS F4 1MI HLT CE 1MI INTO
9F 1MI LAHF F0 1MI LOCK 90 1MI NOP F2 1MI REP F3 1MI REPE
F2 1MI REPNE F2 1MI REPNZ F3 1MI REPZ 9E 1MI SAHF
F9 1MI STC FD 1MI STD FB 1MI STI 9B 1MI WAIT D7 1MI XLAT
OCTAL
: 2MI CREATE C, DOES> C@ C, 12 C, ;
HEX D5 2MI AAD D4 2MI AAM OCTAL
SCREE╬ 25
\ .386 etc, SHORT etc. 10jul88 JBD
VARIABLE .386VAR .386VAR OFF
: .386? .386VAR @ 0<> ; ( all for 3MI use)
: .386 .386? IF .386VAR ON ELSE .386VAR OFF THEN ; ( toggles)
VARIABLE SHORT
( Use SH before 3MI words for short jump when 386 enabled)
: SH SHORT ON ;
: SH? SHORT @ 0<> ;
SCREE╬ 26
\ 3MI, JA etc. 10jul88 JBDè
: 3MI CREATE C, DOES> .386? NOT
IF C@ C, HERE - 1-
DUP -200 177 WITHIN NOT ABORT" Branch out of Range" C,
ELSE ( all 386 cases) C@ OFFPREFX SH?
IF SHORT OFF C, #)?
IF HERE - 1- C,
ELSE ( D#}) HERE 4 + S>D D- DROP C, THEN
ELSE ( 386 near, not short) 17 C, 20 + C, #)?
IF HERE - 2- ,
ELSE ( D#}) HERE 4 + S>D D- SWAP , ,
THEN THEN THEN WRAP ;
SCREE╬ 27
\ 3MI words 10jul88 JBD
HEX
77 3MI JA 73 3MI JAE 72 3MI JB 76 3MI JBE 72 3MI JC
74 3MI JE 7F 3MI JG 7D 3MI JGE 7C 3MI JL 7E 3MI JLE
76 3MI JNA 72 3MI JNAE 73 3MI JNB 77 3MI JNBE 73 3MI JNC
75 3MI JNE 7E 3MI JNG 7C 3MI JNGE 7D 3MI JNL 7F 3MI JNLE
71 3MI JNO 7B 3MI JNP 79 3MI JNS 75 3MI JNZ 70 3MI JO
7A 3MI JP 7A 3MI JPE 7B 3MI JPO 78 3MI JS 74 3MI JZ
OCTAL
SCREE╬ 28
\ 4MI, 14MI 10jul88 JBD
OCTAL
: 4MI CREATE C, DOES> C@ ONPREFX
C, MEM, WRAP ;
HEX C5 4MI LDS 8D 4MI LEA C4 4MI LES OCTAL
( 14MI is 386 instrucs not covered by 4MI)
: 14MI CREATE C, DOES> C@ ONPREFX 17 C,
C, MEM, WRAP ;
HEX B4 14MI LFS B5 14MI LGS B2 14MI LSS OCTAL
SCREE╬ 29
\ 5MI 10jul88 JBD
: 5MI CREATE C, DOES> ( no numeric operands)
0 ( dummy param for PREFX) SWAP C@ OFFPREFX NIP
SIZE, WRAP ;
( Use with BY, WD or DW to give opnd size, with optional
seg override for source string; dest. uses auto ES: override)
HEX A6 5MI CMPS A4 5MI MOVS AE 5MI SCAS
: CMPSB A6 C, ;
: CMPSW WD OPSET OFF 0 PREFX DROP A7 C, WRAP ;
: CMPSD DW OPSET OFF 0 PREFX DROP A7 C, WRAP ;
: MOVSB A4 C, ;
: MOVSW WD OPSET OFF 0 PREFX DROP A5 C, WRAP ;
: MOVSD DW OPSET OFF 0 PREFX DROP A5 C, WRAP ; è: SCASB AE C, ;
: SCASW WD OPSET OFF 0 PREFX DROP AF C, WRAP ;
: SCASD DW OPSET OFF 0 PREFX DROP AF C, WRAP ; OCTAL
SCREE╬ 30
\ 6MI, LODS etc.; 7MI, DIV etc. 10jul88 JBD
( Use with BY, WD or DW to give opnd size)
: 6MI CREATE C, DOES> C@ 0 SWAP OFFPREFX
SWAP DROP SIZE, WRAP ;
HEX AC 6MI LODS AA 6MI STOS
: LODSB ( no opnds) AC C, ;
: LODSW ( no opnds) DX OPSET OFF PREFX DROP AD C, ;
: LODSD ( no opnds) EDX OPSET OFF PREFX DROP AD C, ;
: STOSB ( no opnds) AA C, ;
: STOSW ( no opnds) DX OPSET OFF PREFX DROP AB C, ;
: STOSD ( no opnds) EDX OPSET OFF PREFX DROP AB C, ; OCTAL
: 7MI CREATE C, DOES> C@ OFFPREFX 366 WR/SM, WRAP ;
SCREE╬ 31
\ 8MI: IN, OUT; 9MI: DEC, INC 10jul88 JBD
: 8MI CREATE C, DOES> C@ OP C! OPSET ON PREFX OP C@
SWAP DUP R16? SWAP R32? OR 1 AND OR SWAP # =
IF C, C, ELSE ( DX) 10 OR C, THEN WRAP ;
HEX E4 8MI IN E6 8MI OUT OCTAL
: 9MI CREATE C, DOES> C@ OP C! OPSET OFF PREFX OP C@
OVER DUP R16? SWAP R32? OR
IF 100 OR SWAP RLOW OP,
ELSE 376 WR/SM, THEN WRAP ;
HEX 8 9MI DEC 0 9MI INC OCTAL
SCREE╬ 32
\ 10MI, RCL etc. 10jul88 JBD
( 1 # m/r shl, cl m/r shl, imm8 # m/r shl are legal forms)
: 10MI CREATE C, DOES> C@ OP C! OPSET ON PREFX OP C@
SPT @ 1+ ROLL ( CL or # ) CL =
IF 322 WR/SM,
ELSE ( #)
SPT @ 1+ ROLL ( imm8 data) DUP 1 =
IF DROP 320 WR/SM,
ELSE ( imm8) OPND ! 300 WR/SM, OPND @ C,
THEN THEN WRAP ;
HEX 10 10MI RCL 18 10MI RCR 0 10MI ROL 8 10MI ROR
38 10MI SAR 20 10MI SHL 20 10MI SAL 28 10MI SHR
OCTAL
èSCREE╬ 33
\ 11MI, CALL and JMP 10jul88 JBD
: 11MI CREATE C, C, DOES> OPADR ! OPSET OFF PREFX
OPADR @ OVER DUP OPND ! DUP #)? SWAP D#)? OR
IF NIP C@ INTER @
IF 1 AND IF 352 ELSE 232 THEN C, OPND @ #)?
IF SWAP , , ELSE -ROT SWAP , , , THEN INTER OFF
ELSE OPND @ #)?
IF SWAP HERE - 2- SWAP 2DUP 1 AND SWAP BIG? NOT AND
IF 2 OP, C, ELSE C, 1- , THEN
ELSE ( D#}) -ROT HERE 5 + S>D D- ROT C, SWAP , , THEN THEN
ELSE OVER S#) =
IF NIP #) SWAP ELSE OVER SD#)?
IF NIP D#) SWAP THEN THEN
377 C, 1+ C@ ?FAR R/M, THEN WRAP ;
HEX 10 E8 11MI CALL 20 E9 11MI JMP OCTAL
SCREE╬ 34
\ 12MI, PUSH and POP 10jul88 JBD
: 12MI ( immed, 32segreg{2bytes}, m/r, segreg, reg opcodes -- )
CREATE C, C, C, C, C, C, DOES>
OPADR ! OPSET OFF PREFX OPADR @ OVER REG?
IF C@ SWAP RLOW OP,
ELSE 1+ OVER SEG16?
IF C@ RLOW SWAP RMID OP,
ELSE OVER UMEMA?
IF COUNT SWAP C@ C, MEM,
ELSE 2+ OVER SEG32?
IF COUNT C, C@ OVER FS = IF C, ELSE 10 + C, THEN DROP
ELSE ( Immed: PUSH only) 2+ SWAP D#?
IF C@ C, SWAP , ,
ELSE ( # ) C@ ( disp op) SWAP DUP BIG?
IF SWAP C, , ELSE ( 8 bits) SWAP 2 OR C, C,
THEN THEN THEN THEN THEN THEN WRAP ;
SCREE╬ 35
\ 12MI, PUSH and POP opcodes 10jul88 JBD
HEX
68 0A0 0F 0FF 36 50 12MI PUSH
0 0A1 0F 8F 07 58 12MI POP
OCTAL
SCREE╬ 36
\ NROLL : TOS to N+1th stack position 10jul88 JBD
( 1 NROLL = SWAP, 2 NROLL = -ROT ) è
VARIABLE NUMROLL ( number to ROLL)
: NROLL ( n --) DUP 0<> ( for 13MIMEM use)
IF DUP NUMROLL ! 0 DO
NUMROLL @ ROLL LOOP ELSE DROP THEN ;
SCREE╬ 37
\ 13MI: 13MISIMM 10jul88 JBD
: 13MISIMM ( immed. source with reg dest)
OPND @ #?
IF OVER B/L? OVER DUP R16? SWAP R32? OR 2DUP AND
-ROT 1 AND SWAP NOT 2 AND OR 200 OP,
SWAP RLOW 300 OR OP @ OP, ,/C,
ELSE ( D# source) 177777 DUP 2DUP AND
-ROT 1 AND SWAP NOT 2 AND OR 200 OP,
SWAP RLOW 300 OR OP @ OP, DROP SWAP , ,
THEN ;
SCREE╬ 38
\ 13MI: 13MIMEM 10jul88 JBD
: 13MIMEM ( dest= mem cases of 13MI)
SPT @ ROLL DUP REG?
IF OP C@ WMEM,
ELSE ( #) #?
IF SPT @ PICK B/L? DUP NOT 2 AND 200 OR SIZE,
SPT @ NROLL OP @ MEM,
SIZE @ AND ,/C,
ELSE ( D#) 177777 DUP NOT 2 AND 200 OR SIZE,
SPT @ NROLL OP @ MEM,
DROP SWAP , , THEN THEN ;
SCREE╬ 39
\ 13MI, ADD etc. 10jul88 JBD
: 13MI CREATE C, C, DOES> COUNT OP C! C@ LOGICAL !
OPSET ON PREFX DUP REG? ( dest a reg?)
IF OVER REG? ( source a reg also?)
IF OP @ OVER W, SWAP RR,
ELSE OVER DUP UMEM? SWAP U#)? OR ( memory source?)
IF OP @ 2 OR WMEM,
ELSE ( # or D#) OVER OPND ! NIP DUP RLOW 0= ( accum?)
IF OP @ 4 OR OVER W, OPND @ #?
IF R16? ,/C, ELSE ( D#) DROP SWAP , , THEN
ELSE 13MISIMM ( immed. source, dest reg but not accum)
THEN THEN THEN
ELSE ( mem dest.) 13MIMEM THEN WRAP ;
SCREE╬ 40
è\ 15MI, SETcond 10jul88 JBD
: 15MI CREATE C, DOES> C@ OFFPREFX 17 C, 220 OR C,
DUP R8?
IF RLOW 300 OP,
ELSE ( mem) 0 ( rmid) MEM, THEN WRAP ;
HEX
7 15MI SETA 3 15MI SETAE 2 15MI SETB 6 15MI SETBE 2 15MI SETC
4 15MI SETE F 15MI SETG 0D 15MI SETGE 0C 15MI SETL 0E 15MI SETLE
6 15MI SETNA 2 15MI SETNAE 3 15MI SETNB 7 15MI SETNBE
3 15MI SETNC 5 15MI SETNE 0E 15MI SETNG 0C 15MI SETNGE
0D 15MI SETNL 0F 15MI SETNLE 1 15MI SETNO 0B 15MI SETNP
9 15MI SETNS 5 15MI SETNZ 0 15MI SETO 0A 15MI SETP
0A 15MI SETPE 0B 15MI SETPO 8 15MI SETS 4 15MI SETZ
OCTAL
SCREE╬ 41
\ 16MI + 17MI, CBW,CWD etc, PUSHA/POPA etc, IRET/D 10jul88 JBD
: 16MI CREATE C, DOES> USE? IF 146 C, ( 66h) THEN
C@ C, WRAP ;
HEX 99 16MI CWD 98 16MI CBW 60 16MI PUSHA 9C 16MI PUSHF
61 16MI POPA 9D 16MI POPF CF 16MI IRET
OCTAL
: 17MI CREATE C, DOES> USE? NOT IF 146 C, ( 66h) THEN
C@ C, WRAP ;
HEX 99 17MI CDQ 98 17MI CWDE 60 17MI PUSHAD 9C 17MI PUSHFD
61 17MI POPAD 9D 17MI POPFD CF 17MI IRETD
OCTAL
SCREE╬ 42
\ 18MI, SHLD/SHRD ( non-standard modr/m byte) 10jul88 JBD
( cl reg m/r shld, imm8 # reg m/r shld are legal forms)
VARIABLE CLFLG : CL? CL = 0<> ; : CL CL CLFLG ON ;
: CLFLG? CLFLG @ 0<> ;
: 18MI CREATE C, DOES> C@ ONPREFX 17 C,
SPT @ 2+ ROLL ( CL or # ) CL?
IF 1+ C,
ELSE ( # ) SPT @ 2+ ROLL OPND C! C, THEN
DUP REG? ( dest a reg?)
IF ( source a reg also) SWAP RR, CLFLG?
IF CLFLG OFF ELSE OPND C@ ( imm8) C, THEN
ELSE ( dest mem, source reg)
SPT @ ROLL MEM, CLFLG?
IF CLFLG OFF ELSE OPND C@ ( imm8) C, THEN
THEN WRAP ;
HEX A4 18MI SHLD AC 18MI SHRD OCTAL
SCREE╬ 43è
\ 19MI, LAR + LSL, BSF + BSR 10jul88 JBD
: 19MI CREATE C, DOES> C@ ONPREFX 17 C, C,
OVER REG? ( source a reg also?)
IF RR,
ELSE ( mem source) MEM, THEN WRAP ;
HEX 02 19MI LAR 03 19MI LSL
BC 19MI BSF BD 19MI BSR OCTAL
SCREE╬ 44
\ 20MI, LGDT etc. 10jul88 JBD
( 2nd op, rmid -- )
: 20MI CREATE C, C, DOES> DUP OPADR ! C@ OFFPREFX
17 C, C, OPADR @ 1+ C@ ( rmid)
OVER REG?
IF SWAP RLOW OR 300 OP,
ELSE ( mem) MEM, THEN WRAP ;
HEX 10 1 20MI LGDT 18 1 20MI LIDT 10 0 20MI LLDT
18 0 20MI LTR 0 1 20MI SGDT 8 1 20MI SIDT
0 0 20MI SLDT 20 1 20MI SMSW 8 0 20MI STR
20 0 20MI VERR 28 0 20MI VERW
OCTAL
SCREE╬ 45
\ 21MI, BT etc. 10jul88 JBD
( reg m/r bt, imm8 # m/r bt are legal forms)
( N.B.: non-standard modr/m byte!)
: 21MI CREATE C, DOES> C@ OP C! OPSET ON PREFX 17 C,
SPT @ ROLL ( reg or # ) DUP #? ( source immed?)
IF DROP 272 C, SPT @ ROLL OPND C! DUP REG? ( dest a reg?)
IF RLOW 300 OR OP C@ OR C, OPND C@ C,
ELSE ( mem dest) OP C@ MEM, OPND C@ C, THEN
ELSE ( reg source ) OPND ! OP C@ 203 OR C,
DUP REG? ( dest a reg also?)
IF OPND @ ( source reg) RR,
ELSE ( dest mem, source reg) OPND @ MEM, THEN
THEN WRAP ;
HEX 20 21MI BT 38 21MI BTC 30 21MI BTR 28 21MI BTS
OCTAL
SCREE╬ 46
\ 22MI, INS etc. 10jul88 JBD
: 22MI CREATE C, DOES> ( DX -- )
SWAP DROP ( DX not needed in code)
0 ( dummy param for PREFX ) SWAP C@ OFFPREFX NIP
SIZE, WRAP ;
( Use with BY, WD or DW to give operand size.) è
HEX 6C 22MI INS 6E 22MI OUTS
: INSB 6C C, ;
: INSW WD OPSET OFF 0 PREFX DROP 6D C, WRAP ;
: INSD DW OPSET OFF 0 PREFX DROP 6D C, WRAP ;
: OUTSB 6E C, ;
: OUTSW WD OPSET OFF 0 PREFX DROP 6F C, WRAP ;
: OUTSD DW OPSET OFF 0 PREFX DROP 6F C, WRAP ;
OCTAL
SCREE╬ 47
\ 23MI, MOVSX and MOVZX 10jul88 JBD
: 23MI CREATE C, DOES> C@ ONPREFX 17 C,
2 PICK R8? IF C, ELSE SIZE, THEN
OVER REG? ( source a reg also?)
IF RR,
ELSE ( mem source) MEM, THEN WRAP ;
HEX BE 23MI MOVSX B6 23MI MOVZX OCTAL
SCREE╬ 48
\ TEST: TESTMEM 10jul88 JBD
: TESTMEM ( dest= mem cases of TEST)
SPT @ ROLL DUP REG?
IF 204 WMEM,
ELSE ( # ) #?
IF 366 SIZE, 0 MEM, SIZE @ ,/C,
ELSE ( D# ) 366 SIZE, 0 MEM, SWAP , ,
THEN THEN ;
SCREE╬ 49
\ TEST 10jul88 JBD
: TEST OPSET ON PREFX
DUP REG? ( dest a reg?)
IF OVER REG? ( source a reg also?)
IF 204 OVER W, SWAP RR,
ELSE OVER DUP UMEM? SWAP U#)? OR ( memory source?)
IF 204 WMEM,
ELSE ( # or D# ) OVER OPND ! NIP DUP RLOW 0= ( ACC? )
IF 250 OVER W,
ELSE 366 OVER W, DUP RLOW 300 OP, THEN
DUP R32? IF ( #D) DROP SWAP , ,
ELSE R16? ,/C, THEN THEN THEN
ELSE ( mem dest.) TESTMEM THEN WRAP ;
SCREE╬ 50
\ ESC, INT, XCHG 10jul88 JBDèHEX
: ESC ( rm, 6-bit const -- ) RLOW 0D8 OP, R/M, ;
: INT ( n -- ) 0CD C, C, ; ( N.B.: no # )
: XCHG ( mr1 mr2 -- ) OPSET ON PREFX DUP REG?
IF DUP DUP AX = SWAP EAX = OR
IF DROP RLOW 90 OP, ELSE OVER DUP AX = SWAP EAX = OR
IF NIP RLOW 90 OP, ELSE 86 WR/SM, THEN THEN
ELSE ROT 86 WR/SM, THEN WRAP ;
SCREE╬ 51
\ MOV: MOVRGSG2 10jul88 JBD
: MOVRGSG2 ( -- ss dst ) ( Continuation from MOVRGSG1)
OVER SEG?
IF SWAP 8C C, RR,
ELSE OVER DUP #? SWAP D#? OR
IF DUP DUP R16? SWAP R32? OR SWAP
RLOW OVER 8 AND OR B0 OP,
SWAP D#? IF DROP SWAP , , ELSE ,/C, THEN
ELSE 8A OVER W, R/M, THEN THEN ;
SCREE╬ 52
\ MOV: MOVRGSG1 10jul88 JBD
: MOVRGSG1 ( -- ss dst ) ( dest either REG or SEG)
DUP SEG?
IF 8E C, R/M,
ELSE DUP REG?
IF ( direct memory source? ) OVER DUP
#)? SWAP D#)? OR OVER RLOW 0= AND
IF A0 SWAP W, D#)? IF SWAP , , ELSE , THEN
ELSE ( all other cases ) MOVRGSG2 THEN THEN THEN ;
SCREE╬ 53
\ MOV: MOVMEM 10jul88 JBD
( dest a memory expression, so source is reg or immed.)
: MOVMEM ( ss dst -- ) ( dest a memory expression)
SPT @ ( PREFX handles increment for double displacements)
ROLL DUP SEG? ( source a segreg?)
IF 8C C, MEM,
ELSE DUP #?
IF DROP C6 SIZE, 0 MEM, SIZE @ ,/C,
ELSE DUP D#?
IF DROP C6 SIZE, 0 MEM, SWAP , ,
ELSE OVER #)? OVER RLOW 0= AND
IF A2 SWAP W, DROP , ELSE 88 OVER W, R/M,
THEN THEN THEN THEN ;
èSCREE╬ 54
\ MOV, MOVSPL 10jul88 JBD
: MOVSPL 0F C, DUP SPL? ( dest SPL?)
IF DUP CTL? IF 22 ELSE DUP DBG? IF 23 ELSE 26 THEN THEN
C, RMID SWAP RLOW OR C0 OR C,
ELSE ( source is SPL) SPT @ PICK
DUP CTL? IF DROP 20 ELSE DBG? IF 21 ELSE 24 THEN THEN
C, RLOW SWAP RMID OR C0 OR C, THEN ;
: MOV ( source dest--) OPSET ON PREFX
DUP SPL? SPT @ 1+ PICK SPL? OR ( dest or source SPL?)
IF MOVSPL
ELSE DUP DUP REG? SWAP SEG? OR ( dest reg or segreg?)
IF MOVRGSG1 ELSE MOVMEM THEN THEN WRAP ;
SCREE╬ 55
\ ARPL, CLTS, BOUND, ENTER, LEAVE 10jul88 JBD
OCTAL
( r16 m/r16 ARPL)
: ARPL ( N.B.: non-standard modr/m byte!)
OPSET ON PREFX 143 C, DUP R16?
IF SWAP RR, ELSE ( mem dest) SPT @ ROLL MEM, THEN WRAP ;
: CLTS ( --) 17 C, 6 C, ;
: BOUND ( mem reg bound) OPSET ON PREFX 142 C, MEM, WRAP ;
: ENTER ( imm8 imm16 enter)
310 C, , C, ;
: LEAVE ( --) 311 C, ;
SCREE╬ 56
\ JCXZ, JECXZ 10jul88 JBD
: JCXZ ( adr, #} or D#} -- ) USE?
IF 146 C, THEN 343 C, #)?
IF HERE - 2- ,
ELSE ( D#}) HERE 4 + S>D D- SWAP , , THEN ;
: JECXZ ( adr, #} or D#} -- ) USE? NOT
IF 146 C, THEN 343 C, #)?
IF HERE - 2- ,
ELSE ( D#}) HERE 4 + S>D D- SWAP , , THEN ;
SCREE╬ 57
\ 7MI and 13MI, Opcode Definitions. 10jul88 JBD
( Put here to avoid conflicts with ordinary NOT, AND and OR)
HEX
30 7MI DIV 38 7MI IDIV 28 7MI IMUL 20 7MI MUL 10 7MI NOT è
0 10 13MI ADC 0 0 13MI ADD 2 20 13MI AND 0 38 13MI CMP
2 8 13MI OR 0 18 13MI SBB 0 28 13MI SUB 2 30 13MI XOR
DECIMAL
SCREE╬ 58
\ Structured Conditionals 10jul88 JBD
: A?>MARK ( -- f addr ) TRUE HERE 0 C, ;
: A?>RESOLVE ( f addr -- ) HERE OVER 1+ - SWAP C! ?CONDITION ;
: A?<MARK ( -- f addr ) TRUE HERE ;
: A?<RESOLVE ( f addr -- ) HERE 1+ - C, ?CONDITION ;
' A?>MARK ASSEMBLER IS ?>MARK
' A?>RESOLVE ASSEMBLER IS ?>RESOLVE
' A?<MARK ASSEMBLER IS ?<MARK
' A?<RESOLVE ASSEMBLER IS ?<RESOLVE
HEX
75 CONSTANT 0= 74 CONSTANT 0<> 79 CONSTANT 0<
78 CONSTANT 0>= 7D CONSTANT < 7C CONSTANT >=
7F CONSTANT <= 7E CONSTANT > 73 CONSTANT U<
72 CONSTANT U>= 77 CONSTANT U<= 76 CONSTANT U>
71 CONSTANT OV
DECIMAL
SCREE╬ 59
\ Structured Conditionals 10jul88 JBD
HEX
: IF C, ?>MARK ;
: THEN ?>RESOLVE ;
: ELSE 0EB IF 2SWAP THEN ;
: BEGIN ?<MARK ;
: UNTIL C, ?<RESOLVE ;
: AGAIN 0EB UNTIL ;
: WHILE IF ;
: REPEAT 2SWAP AGAIN THEN ;
: DO # CX MOV HERE ;
: NEXT >NEXT #) JMP ;
: 1PUSH >NEXT 1- #) JMP ;
: 2PUSH >NEXT 2- #) JMP ;
DECIMAL