/* last updated 14 November 1985 */


/* INTEL 8086 DIS-ASSEMBLER */


DECLARE	ONE$BYT$ASC(*) BYTE DATA

	('XLAT,LAHF,SAHF,PUSHF,POPF,',
	'AAA,DAA,AAS,DAS,CBW,CWD,RET,RETfar,',
	'Brkpnt,INTO,IRET,CLC,CMC,CLD,CLI,HLT,',
	'LOCK,STC,NOP,STD,STI,WAIT,XLAT,');


DECLARE	ONE$BYT$COD(*) BYTE DATA

	(0D7H,09FH,09EH,09CH,09DH,
	037H,027H,03FH,02FH,098H,
	099H,0C3H,0CBH,0CCH,0CEH,
	0CFH,0F8H,0F5H,0FCH,0FAH,
	0F4H,0F0H,0F9H,090H,0FDH,
	0FBH,09BH,0D7H);


DECLARE	ONE$BYT$STR$ASC(*)  BYTE DATA 

	('MOVS ,LODS ,STOS ,CMPS ,SCAS ,');

DECLARE	ONE$BYT$STR$COD(*) BYTE DATA
	( 0A4H,0ACH,0AAH,0A6H,0AEH );

DECLARE	ONE$DISP8$ASC(*) BYTE DATA

	('JMP,JZ,JL,JLE,JB,JBE,',
	'JP,JO,JS,JNZ,JNL,JNLE,JNB,',
	'JNBE,JNP,JNO,JNS,LOOP,LOOPZ,',
	'LOOPNZ,JCXZ,');

DECLARE	ONE$DISP8$COD(*) BYTE DATA

	(0EBH,074H,07CH,07EH,072H,076H,
	07AH,070H,078H,075H,07DH,
	07FH,073H,077H,07BH,071H,
	079H,0E2H,0E1H,0E0H,0E3H);


DECLARE	ONE$BYT$MOD$REG$RM$ASC(*) BYTE DATA

	('LEA,LDS,LES,');

DECLARE	ONE$BYT$MOD$REG$RM$COD(*) BYTE DATA

	(08DH,0C5H,0C4H);


DECLARE	ONE$BYT$DISP16$ASC LITERALLY 'TWO$BYT$MOD$RM$ASC(9)';

	/* CALL,JMP */


DECLARE	ONE$BYT$DISP16$COD(*) BYTE DATA

	(0E8H,0E9H);

DECLARE ONE$BYT$OFFSEG$COD(*) BYTE DATA

	(09AH,0EAH);

DECLARE ONE$BYT$OFFSEG$ASC LITERALLY 'TWO$BYT$MOD$RM$ASC(9)';

	/* CALL,JMP */


DECLARE	ONE$BYT$DATA$ASC LITERALLY 'ONE$BYT$ASC(50)';

	/* RET, RETfar */


DECLARE	ONE$BYT$DATA$COD(*) BYTE DATA

	(0C2H,0CAH);

DECLARE ONE$BYT$IMMED$ACC$ASC LITERALLY 'ONE$BYT$MODREGRM$DW$ASC(4)';

	/* ADD,ADC,SUB,SBB,CMP,AND,OR,XOR,TEST */


DECLARE ONE$BYT$IMMED$ACC$COD(*) BYTE DATA

	(004H,014H,02CH,01CH,03CH,024H,00CH,034H,0A8H);

DECLARE ONE$BYT$REG$ASC(*) BYTE DATA

	('PUSH,POP,INC,DEC,');

DECLARE ONE$BYT$REG$COD(*) BYTE DATA

	(050H,058H,040H,048H);

DECLARE ONE$BYT$MODREGRM$DW$ASC(*) BYTE DATA

	('MOV,ADD,ADC,SUB,SBB,CMP,AND,OR,XOR,TEST,');

DECLARE ONE$BYT$MODREGRM$DW$COD(*) BYTE DATA

	(088H,000H,010H,028H,018H,038H,020H,008H,030H);

DECLARE ONE$BYT$MODREGRM$W$ASC(*) BYTE DATA

	('XCHG,TEST,');

DECLARE ONE$BYT$MOD$REG$RM$W$COD(*) BYTE DATA

	(086H,084H);

DECLARE ODDS$AND$ENDS$ASC(*) BYTE DATA

	('IN,OUT,REP ,REPNZ ,REPZ ,REPz ,INT,ESC,');



DECLARE	TWO$BYT$MOD$RM$ASC(*) BYTE DATA

	('PUSH,POP,CALL,JMP,CALLfar,JMPfar,');

DECLARE	TWO$BYT$MOD$RM$COD(*) WORD DATA

	(0FF30H,08F00H,0FF10H,0FF20H,0FF18H,0FF28H);


DECLARE	TWO$BYT$MOD$RM$WRD$ASC(*) BYTE DATA

	('INC,DEC,NEG,MUL,IMUL,DIV,IDIV,NOT,');

DECLARE	TWO$BYT$MOD$RM$WRD$COD(*) WORD DATA

	(0FE00H,0FE08H,0F618H,0F620H,0F628H,0F630H,0F638H,0F610H);


DECLARE	TWO$BYT$NOBIT$ASC(*) BYTE DATA

	('AAM,AAD,');

DECLARE	TWO$BYT$NOBIT$COD(*) WORD DATA

	(0D40AH,0D50AH);

DECLARE	TWO$BYT$MOD$RM$VW$ASC(*) BYTE DATA

	('SHL/sal,SHR,SAR,ROL,ROR,RCL,RCR,');

DECLARE	TWO$BYT$MOD$RM$VW$COD(*) WORD DATA

	(0D020H,0D028H,0D038H,0D000H,0D008H,0D010H,0D018H);


DECLARE TWO$BYT$W$IMMED$ASC(*) BYTE DATA

	('MOV,AND,TEST,OR,XOR,');

DECLARE TWO$BYT$W$IMMED$COD(*) WORD DATA

	(0C600H,08020H,0F600H,08008H,08030H);

DECLARE	TWO$BYT$SW$IMMED$ASC LITERALLY 'ONE$BYT$MODREGRM$DW$ASC(4)';

	/* ADD, ADC, SUB, SBB, CMP */


DECLARE TWO$BYT$SW$IMMED$COD(*) WORD DATA

	(08000H,08010H,08028H,08018H,08038H);

DECLARE	SEG$REG$ASC(*) BYTE DATA

	('ES,CS,SS,DS,');

DECLARE	WORD$REG$ASC(*) BYTE DATA

	('AX,CX,DX,BX,SP,BP,SI,DI,');

DECLARE	BYTE$REG$ASC(*) BYTE DATA

	('AL,CL,DL,BL,AH,CH,DH,BH,');

DECLARE RM$FIELD$ASC(*) BYTE DATA

	 ('[BX][SI],[BX][DI],[BP][SI],',
	'[BP][DI],[SI],[DI],[BP],[BX],');

DECLARE BYTE$OR$WORD(*) BYTE DATA

	('BYTE ,WORD ,');

DECLARE DI$SI$STRING(*) BYTE DATA

	('(DI) ,(SI),');


DECLARE ERROR$MESS(*) BYTE DATA

	('not used,invalid,');


DECLARE
	PAGE$LEN	WORD,		/* PAGE LENGTH */
/*	TEMP$PAGE	BYTE,		   TEMPORY PAGE LENGTH */
/*	TEMP$CODE$B	BYTE,		   TEMPORY BYTE OPCODE */
	TEMP$CODE$W	WORD,		/* TEMPORY WORD OPCODE */
	INDEX		WORD,		/* COPY POINTER */
	DISP$WORD	WORD,		/* DISPLACEMENTS */
	D$BIT		BYTE,		/* DIRECTION BIT */
	DISP$WORD1	WORD;

/*	DISP$WORD1	WORD,		DISPLACMENT */
/*	W$BIT		BYTE,		WORD INSTR, */

DECLARE TEMP$PAGE LITERALLY 'BRK1$FLAG';

DECLARE TEMP$CODE$B LITERALLY 'BRK1$SAVE';

DECLARE W$BIT LITERALLY 'LAST$COMMAND';

DECLARE DISP$BYTE LITERALLY 'CHECK$SUM';	/* RE-USE CHECK$SUM, SAVE SPACE */

DECLARE SEG$OVER LITERALLY 'WORD$MODE';		/* RE-USE WORD$MODE, SAVE SPACE */


DECLARE
	BUFFER(52) BYTE;

DECLARE (ASCII$PTR, HEX$PTR) BYTE;



DECLARE
		SPACE		LITERALLY	'020H',
		NULL		LITERALLY	'000H',
		COMMA		LITERALLY	'02CH',
		COLUMN$1	LITERALLY	'26';


FIND$AND$COPY:

	/* LOCATE THE INDEX'TH TEXT STRING AND COPY
	 IT TO BUFFER(ASCII$PTR UPDATE ASCII$PTR */


PROCEDURE (STRING$PTR,INDEX);

	DECLARE STRING$PTR POINTER;
	DECLARE ITEM BASED STRING$PTR(1) BYTE;
	DECLARE (INDEX, OFFSET) BYTE;

	I = 0;
	OFFSET = 0;
	DO WHILE INDEX <> I;
		DO WHILE ITEM(OFFSET) <> COMMA;
		OFFSET = OFFSET + 1;
		END;
	I = I + 1;			/* FOUND COMMA */
	OFFSET = OFFSET	+ 1;		/* SKIP COMMA */
	END;

	/* COPY FROM STRING$PTR TO BUFFER(ASCII$PTR)
	AND SETS NEXT AVAILIABLE ADDRESS */


	DO WHILE ITEM(OFFSET) <> COMMA;
	BUFFER(ASCII$PTR) = ITEM(OFFSET);
	OFFSET = OFFSET + 1;
	ASCII$PTR = ASCII$PTR + 1;
	END;

END FIND$AND$COPY;


SCAN$BYT$CODES:

	/* TEST CURRENT CODE AGAINST GIVEN BYTE LIST 
	RETURN INDEX POINTING AT STRING */

PROCEDURE (CODE,CODE$PTR,NUMBER) BYTE;

	DECLARE CODE$PTR POINTER;
	DECLARE ( CODE, NUMBER ) BYTE;
	DECLARE CODES$LIST BASED CODE$PTR(1) BYTE;

	INDEX = FINDB(CODE$PTR,CODE,NUMBER);
	IF INDEX = 0FFFFH THEN RETURN FALSE;
	RETURN TRUE;

END SCAN$BYT$CODES;


SCAN$WRD$CODES:

	/* TEST CURRENT CODE AGAINST A GIVEN WORD LIST
	RETURN INDEX POINTING AT STRING */

PROCEDURE (CODE,CODE$PTR,NUMBER) BYTE;

	DECLARE CODE$PTR POINTER;
	DECLARE CODE WORD;
	DECLARE CODES$LIST BASED CODE$PTR(1) WORD;
	DECLARE NUMBER BYTE;

	INDEX = FINDW(CODE$PTR,CODE,NUMBER);
	IF INDEX = 0FFFFH THEN RETURN FALSE;
	RETURN TRUE;

END SCAN$WRD$CODES;


CONV$TO$HEX$STORE:

	/* CONVERT A BYTE TO HEX AND STORE AT BUFFER(POINTER) */

PROCEDURE (BITE,TO$OFFSET);

	DECLARE (BITE, TO$OFFSET) BYTE;

	DO;
	BUFFER(TO$OFFSET)   = ASCII(SHR(BITE,4) AND 0FH);
	BUFFER(TO$OFFSET+1) = ASCII(BITE AND 0FH);

	END;

END CONV$TO$HEX$STORE;


HEX$TO$BUFF:

	/* CONVERT BYTE TO HEX AND STORE IN CODE FIELD */

PROCEDURE (BITE);

	DECLARE BITE BYTE;

	DO;
	CALL CONV$TO$HEX$STORE(BITE,HEX$PTR);
	HEX$PTR = HEX$PTR + 2;
	END;

END HEX$TO$BUFF;


PRINT$HEX:

	/* CONVERT BYTE TO HEX AND STORE IN ASCII FIELD */

PROCEDURE (BITE);

	DECLARE BITE BYTE;

	DO;
	CALL CONV$TO$HEX$STORE(BITE,ASCII$PTR);
	ASCII$PTR = ASCII$PTR + 2;
	END;

END PRINT$HEX;


PRINT$ASCII:

	/* STORE ASCII CHARACTER IN ASCII FIELD */

PROCEDURE (ASCII$CHAR);

	DECLARE ASCII$CHAR BYTE;

	DO;
	BUFFER(ASCII$PTR) = ASCII$CHAR;
	ASCII$PTR = ASCII$PTR + 1;
	END;

END PRINT$ASCII;


PRINT$HEX$STRING:

	/* PRINT N HEX BYTES TO HEX$PTR */

PROCEDURE(N);

	DECLARE N BYTE;

	DO I=1 TO N;
	CALL HEX$TO$BUFF(MEMORY$WORD$ARG1);
	ARG1.OFF = ARG1.OFF + 1;
	END;

END PRINT$HEX$STRING;


PRINT$HEX$BYTE:

	/* PRINT 8 BIT BYTE 0XXH */

PROCEDURE (BITE);

	DECLARE BITE BYTE;

	DO;
	CALL PRINT$ASCII('0');
	CALL PRINT$HEX(BITE);
	CALL PRINT$ASCII('H');
	END;

END PRINT$HEX$BYTE;


PRINT$HEX$WORD:

	/* PRINT HEX 16 BIT WORD 0XXXXH */

PROCEDURE (WERD);

	DECLARE WERD WORD;

	DO;
	CALL PRINT$ASCII('0');
	IF (HIGH(WERD)) <> 0 THEN CALL PRINT$HEX(HIGH(WERD));
	CALL PRINT$HEX(LOW(WERD));
	CALL PRINT$ASCII('H');
	END;

END PRINT$HEX$WORD;


PRINT$HEX$ADDR:

	/* PRINT 16 BIT ADDRESS (0XXXXH) */

PROCEDURE (ADDR);

	DECLARE ADDR WORD;

	DO;
	CALL PRINT$ASCII('(');
	CALL PRINT$HEX$WORD(ADDR);
	CALL PRINT$ASCII(')');
	END;

END PRINT$HEX$ADDR;


DO$MOD$RM:

	/* DECODE THE MOD XXX R/M FIELD OF SUPPLIED BYTE */

PROCEDURE (MOD$RM);

	DECLARE MOD$RM BYTE;

	DO;
	IF (MOD$RM AND 11000000B) = 0C0H
	THEN	/* R/M IS A REGISTER */
		DO;
		IF W$BIT THEN /* R/M IS WORD REGISTERS */
			DO;
			CALL FIND$AND$COPY(@WORD$REG$ASC,(MOD$RM AND 7));
			END;
		ELSE
			DO;
			CALL FIND$AND$COPY(@BYTE$REG$ASC,(MOD$RM AND 7));
			END;
		END;
	ELSE							/* R/M IS AN ADDRESS */
		DO;
		IF SEG$OVER <> 0 THEN
			DO;
			CALL FIND$AND$COPY(@SEG$REG$ASC,(ROR(SEG$OVER,3) AND 11B));
			CALL PRINT$ASCII(':');
			END;
		IF (MOD$RM AND 11000111B) = 00$000$110B 	/* EA IS LOW HIGH */
		THEN
			DO;
			CALL PRINT$ASCII('(');
			CALL PRINT$HEX$WORD(MEMORY$WORD$ARG1);
			CALL PRINT$ASCII(')');
			CALL PRINT$HEX$STRING(2);
			END;
		ELSE
			DO;
			CALL FIND$AND$COPY(@RM$FIELD$ASC,(MOD$RM AND 7));
			DISP$WORD = 0;
			IF (MOD$RM AND 0C0H) <> 0
			THEN			/* DISP IS 8 OR 16 BITS */
				DO;
				DISP$WORD = MEMORY$WORD$ARG1;
				IF (MOD$RM AND 0C0H) = 80H
				THEN		/* DISP IS 16 BITS */
					DO;
					IF DISP$WORD > 8000H	/* IS DISP NEGATIVE? */
					THEN
						DO;
						CALL PRINT$ASCII('-');
						DISP$WORD = (NOT(DISP$WORD))+1;
						END;
					ELSE
						DO;
						CALL PRINT$ASCII('+');
						END;
					CALL PRINT$HEX$WORD(DISP$WORD);
					CALL PRINT$HEX$STRING(2);
					END;
				ELSE	/* DISP IS 8 BITS */
					DO;
					IF LOW(DISP$WORD) > 80H	/* IS DISP NEGATIVE? */
					THEN
						DO;
						CALL PRINT$ASCII('-');
						DISP$WORD = (NOT(DISP$WORD))+1;
						END;
					ELSE
						DO;
						CALL PRINT$ASCII('+');
						END;
					CALL PRINT$HEX$BYTE(LOW(DISP$WORD));
					CALL PRINT$HEX$STRING(1);
					END;
				END;
			END;
		END;
	END;

END DO$MOD$RM;


DO$REG$FIELD:

	/* SORT OUT REG FIELD */

PROCEDURE (REGISTER);

	DECLARE REGISTER BYTE;

	DO;
	REGISTER = ( ROR(REGISTER,3) AND 0111B);
	IF W$BIT
	THEN /* REG IS WORD REGISTER */
		DO;
		CALL FIND$AND$COPY(@WORD$REG$ASC,(REGISTER));
		END;
	ELSE /* REG IS BYTE REGISTER */
		DO;
		CALL FIND$AND$COPY(@BYTE$REG$ASC,(REGISTER));
		END;
	END;

END DO$REG$FIELD;

/***********************************************************************/


FCMD:		/* CONVERT CODES FROM ARG1.OFF TO END$OFF TO MNEMONICS */

PROCEDURE;


	DO WHILE ARG1.OFF <= END$OFF;

	/* CLEAR OUTPUT BUFFER */

	DO I=0 TO (LENGTH(BUFFER)-1);
		BUFFER(I) = SPACE;
	END;

	ASCII$PTR = 17;
	HEX$PTR = 1;		/* SET START ADDRESSES OF POINTERS */
	D$BIT, SEG$OVER = FALSE;
	W$BIT = TRUE;

	CALL SIO$CRLF;			/* PRINT CRLF ADDRESS */
	CALL SIO$OUT$WORD(ARG1.OFF);	/* PRINT CURRENT ADDRESS */

	TEMP$CODE$B = MEMORY$ARG1;			/* GET BYTE OPCODE */
	CALL PRINT$HEX$STRING(1);			/* PRINT OPCODE BYTE */

	IF (TEMP$CODE$B AND 0FEH) = 0F2H THEN		/* REPEAT */
		DO;
		DISP$BYTE = TEMP$CODE$B;		/* SAVE TEMP$CODE$B */
		TEMP$CODE$B = MEMORY$ARG1;		/* GET NEXT CODE */

		IF (TEMP$CODE$B AND 0E7H) = 26H THEN	/* NEXT CODE IS SEG OVER */
			DO;
			SEG$OVER = TEMP$CODE$B;		/* SET SEG$OVER ON */
			CALL PRINT$HEX$STRING(1);	/* PRINT SEG OVER CODE */
			TEMP$CODE$B = MEMORY$ARG1;	/* GET NEXT CODE */
			END;

		IF SCAN$BYT$CODES((TEMP$CODE$B AND 0FEH),@ONE$BYT$STR$COD,5) = TRUE
		THEN		/* NEXT CODE IS A STRING INSTRUCTION */
			DO;
			CALL PRINT$HEX$STRING(1);
			IF INDEX > 2 THEN		/* REPZ OR REPNZ */
				DO;
				INDEX = 3 + (DISP$BYTE AND 1B);
				END;
			ELSE
				DO;
				INDEX = 2;
				END;
			CALL FIND$AND$COPY(@ODDS$AND$ENDS$ASC,INDEX);
			END;
		ELSE
			DO;
			CALL FIND$AND$COPY(@ODDS$AND$ENDS$ASC,5);	/* PRINT REPz */
			GOTO END$PASS;
			END;
		END;

DO$SEG$OVERRIDE:

	IF (TEMP$CODE$B AND 0E7H) = 26H THEN	/* NEXT CODE IS A SEG OVERRIDE */
		DO;
		SEG$OVER = TEMP$CODE$B;
		TEMP$CODE$B = MEMORY$ARG1;	/* GET NEXT OPCODE */
		IF (TEMP$CODE$B AND 0E7H) = 26H THEN GOTO ERROR$PASS;	/* DOUBLE SEG OVERRIDE */
		CALL PRINT$HEX$STRING(1);	/* PRINT NEXT OPCODE */
		END;

	IF SCAN$BYT$CODES(TEMP$CODE$B,@ONE$BYT$COD,LENGTH(ONE$BYT$COD))=TRUE THEN
		DO;				/* IT MUST BE A ONE BYTE CODE */
		CALL FIND$AND$COPY(@ONE$BYT$ASC,INDEX);
		GOTO END$PASS;
		END;



	IF SCAN$BYT$CODES(TEMP$CODE$B AND 0FEH,@ONE$BYT$STR$COD,5) = TRUE
	THEN
		DO;	/* IT MUST BE A STRING MOVS STOS ETC */
		CALL FIND$AND$COPY(@ONE$BYT$STR$ASC,INDEX);
		CALL FIND$AND$COPY(@BYTE$OR$WORD,TEMP$CODE$B AND 001B);

		IF	(TEMP$CODE$B AND 0FEH) <> 0ACH
		THEN					/* DON'T PRINT "DI" IF "LODS" FOUND */
			DO;
			CALL FIND$AND$COPY(@DI$SI$STRING,0);
			END;
		IF SEG$OVER <> 0
		THEN		/* PRINT WHICH SEGMENT TO OVERRIDE */
			DO;
			IF (TEMP$CODE$B AND 1010B) = 1010B	/* ES CANNOT BE OVER RIDDEN */
			THEN
				DO;		/* ERROR ON SCAS/STOS SEGOVER:DI */
				CALL FIND$AND$COPY(@ERROR$MESS,1);
				END;
			ELSE
				DO;
				CALL FIND$AND$COPY(@SEG$REG$ASC,(ROR(SEG$OVER,3) AND 11B));
				CALL PRINT$ASCII(':');
				END;
			END;
		IF (TEMP$CODE$B AND 1000B) = 0	/* IS IT MOVS OR CMPS ? */
		THEN
			DO;
			CALL FIND$AND$COPY(@DI$SI$STRING,1);
			END;
		IF (TEMP$CODE$B AND 0FEH) = 0ACH	/* IS IT LODS ? */
			THEN
				DO;
				CALL FIND$AND$COPY(@DI$SI$STRING,1);
				END;
		GOTO END$PASS;
		END;

	IF SCAN$BYT$CODES(TEMP$CODE$B,@ONE$DISP8$COD,LENGTH(ONE$DISP8$COD)) = TRUE
	THEN
		DO;			/* IT MUST BE A TWO BYTE JUMP PC + DISP8 */
		CALL FIND$AND$COPY(@ONE$DISP8$ASC,INDEX);
		ASCII$PTR = COLUMN$1;
		DISP$WORD = LOW(MEMORY$WORD$ARG1);
		CALL PRINT$HEX$STRING(1);
		IF (DISP$WORD AND 80H) = 80H THEN	/* NEGATIVE JUMP */
			DO;
			DISP$WORD = DISP$WORD OR 0FF00H;
			END;
		DISP$WORD = ARG1.OFF + DISP$WORD;
		CALL PRINT$HEX$WORD(DISP$WORD);
		GOTO END$PASS;
		END;

	IF SCAN$BYT$CODES(TEMP$CODE$B,@ONE$BYT$MOD$REG$RM$COD,3) = TRUE
	THEN
		DO;				/* LEA,LDS & LES */
		CALL FIND$AND$COPY(@ONE$BYT$MOD$REG$RM$ASC,INDEX);
		ASCII$PTR = COLUMN$1;
		TEMP$CODE$B = MEMORY$ARG1;
		CALL PRINT$HEX$STRING(1);
		CALL DO$REG$FIELD(TEMP$CODE$B);
		CALL PRINT$ASCII(',');
		CALL DO$MOD$RM(TEMP$CODE$B);
		GOTO END$PASS;
		END;


	IF SCAN$BYT$CODES(TEMP$CODE$B,@ONE$BYT$DISP16$COD,2) = TRUE
	THEN
		DO;		/* THREE BYTE JMP OR CALL TO 16 BIT DISP */
		CALL FIND$AND$COPY(@ONE$BYT$DISP16$ASC,INDEX);
		ASCII$PTR = COLUMN$1;
		DISP$WORD = MEMORY$WORD$ARG1;
		CALL PRINT$HEX$STRING(2);
		DISP$WORD = DISP$WORD + ARG1.OFF;
		CALL PRINT$HEX$WORD(DISP$WORD);
		GOTO END$PASS;
		END;


	IF SCAN$BYT$CODES(TEMP$CODE$B,@ONE$BYT$OFFSEG$COD,2) = TRUE
	THEN
		DO;		/* FIVE BYTE FAR JMP OR CALL TO NEW CS:IP */
		CALL FIND$AND$COPY(@ONE$BYT$OFFSEG$ASC,INDEX);
		ASCII$PTR = COLUMN$1;
		DISP$WORD1 = MEMORY$WORD$ARG1;		/* GET OFFSET */
		CALL PRINT$HEX$STRING(2);
		DISP$WORD = MEMORY$WORD$ARG1;		/* GET SEGMENT */
		CALL PRINT$HEX$STRING(2);
		CALL PRINT$HEX$WORD(DISP$WORD);		/* PRINT SEGMENT */
		CALL PRINT$ASCII(':');
		CALL PRINT$HEX$WORD(DISP$WORD1);	/* PRINT OFFSET */
		GOTO END$PASS;
		END;

	IF SCAN$BYT$CODES(TEMP$CODE$B,@ONE$BYT$DATA$COD,2) = TRUE
	THEN
		DO;		/* RETURN ADJUSTING STACK POINTER */
		CALL FIND$AND$COPY(@ONE$BYT$DATA$ASC,INDEX);
		ASCII$PTR = COLUMN$1;
		DISP$WORD = MEMORY$WORD$ARG1;
		CALL PRINT$HEX$STRING(2);
		CALL PRINT$HEX$WORD(DISP$WORD);
		GOTO END$PASS;
		END;

	IF SCAN$BYT$CODES((TEMP$CODE$B AND 0FEH),@ONE$BYT$IMMED$ACC$COD,9) = TRUE
	THEN
		DO;		/* ACCUMULATOR IMMEDIATE INSTRUCTIONS */
		CALL FIND$AND$COPY(@ONE$BYT$IMMED$ACC$ASC,INDEX);
		ASCII$PTR = COLUMN$1;
		DISP$WORD = MEMORY$WORD$ARG1;
		IF TEMP$CODE$B AND 1B = 1 THEN	/* WORD TYPE */
			DO;
			CALL FIND$AND$COPY(@WORD$REG$ASC,0);	/* PRINT AX */
			CALL PRINT$ASCII(',');
			CALL PRINT$HEX$STRING(2);
			CALL PRINT$HEX$WORD(DISP$WORD);		/* 16 BIT DATA */
			END;

		ELSE
			DO;
			CALL FIND$AND$COPY(@BYTE$REG$ASC,0);	/* PRINT AL */
			CALL PRINT$ASCII(',');
			CALL PRINT$HEX$STRING(1);
			CALL PRINT$HEX$BYTE(LOW(DISP$WORD));	/* 8 BIT DATA */
			END;
		GOTO END$PASS;
		END;


	IF SCAN$BYT$CODES((TEMP$CODE$B AND 0F8H),@ONE$BYT$REG$COD,4) = TRUE
	THEN
		DO;		/* PUSH POP INC DEC */
		CALL FIND$AND$COPY(@ONE$BYT$REG$ASC,INDEX);
		ASCII$PTR = COLUMN$1;
		CALL FIND$AND$COPY(@WORD$REG$ASC,(TEMP$CODE$B AND 7H));
		GOTO END$PASS;
		END;

	IF SCAN$BYT$CODES((TEMP$CODE$B AND 0FCH),@ONE$BYT$MOD$REG$RM$DW$COD,9) = TRUE
	THEN
		DO;		/* OPCODE * D & W BITS PLUS MOD REG R/M FIELD */
		IF (TEMP$CODE$B AND 1) = 0 THEN W$BIT = FALSE;	/* SET BYTE */
		CALL FIND$AND$COPY(@ONE$BYT$MODREGRM$DW$ASC,INDEX);
		ASCII$PTR = COLUMN$1;
		IF (TEMP$CODE$B AND 2) = 2 THEN D$BIT = TRUE;	/* SET DIRECTION */
		TEMP$CODE$B = MEMORY$ARG1;
		CALL PRINT$HEX$STRING(1);
		IF D$BIT = TRUE
		THEN
			DO;
			CALL DO$REG$FIELD(TEMP$CODE$B);		/* TO REG FIELD */
			CALL PRINT$ASCII(',');
			CALL DO$MOD$RM(TEMP$CODE$B);
			END;
		ELSE
			DO;
			CALL DO$MOD$RM(TEMP$CODE$B);		/* TO MOD R/M FIELD */
			CALL PRINT$ASCII(',');
			CALL DO$REG$FIELD(TEMP$CODE$B);
			END;
		GOTO END$PASS;
		END;

	IF SCAN$BYT$CODES((TEMP$CODE$B AND 0FEH),@ONE$BYT$MODREGRM$W$COD,2) = TRUE
	THEN
		DO;		/* OPCODE + W BIT AND MOD REG R/M */
		IF (TEMP$CODE$B AND 1) = 0 THEN W$BIT = FALSE;	/* SET BYTE */
		CALL FIND$AND$COPY(@ONE$BYT$MODREGRM$W$ASC,INDEX);
		ASCII$PTR = COLUMN$1;
		TEMP$CODE$B = MEMORY$ARG1;
		CALL PRINT$HEX$STRING(1);
		CALL DO$REG$FIELD(TEMP$CODE$B);
		CALL PRINT$ASCII(',');
		CALL DO$MOD$RM(TEMP$CODE$B);
		GOTO END$PASS;
		END;

/* TIDY UP ONE BYTE CODES */

	IF (TEMP$CODE$B AND 11111000B) = 90H		/* XCHG AX,REG */
	THEN
		DO;
		CALL FIND$AND$COPY(@ONE$BYT$MOD$REG$RM$W$ASC,0);
		ASCII$PTR = COLUMN$1;
		CALL FIND$AND$COPY(@WORD$REG$ASC,0);
		CALL PRINT$ASCII(',');
		CALL DO$REG$FIELD(ROL(TEMP$CODE$B,3));
		GOTO END$PASS;
		END;


	IF TEMP$CODE$B = 0CDH THEN			/* INTERRUPT NN */
		DO;
		CALL FIND$AND$COPY(@ODDS$AND$ENDS$ASC,6);
		ASCII$PTR = COLUMN$1;
		CALL PRINT$HEX$BYTE(MEMORY$ARG1);
		CALL PRINT$HEX$STRING(1);
		GOTO END$PASS;
		END;

	IF (TEMP$CODE$B AND 0F0H) = 0B0H THEN		/* MOV IMMED REG */
		DO;
		CALL FIND$AND$COPY(@TWO$BYT$W$IMMED$ASC,0);
		ASCII$PTR = COLUMN$1;
		IF (TEMP$CODE$B AND 8) = 0 THEN W$BIT = FALSE;
		CALL DO$REG$FIELD(ROL(TEMP$CODE$B,3));
		CALL PRINT$ASCII(',');
		IF W$BIT = FALSE
		THEN
			DO;
			CALL PRINT$HEX$BYTE(MEMORY$ARG1);
			CALL PRINT$HEX$STRING(1);
			END;
		ELSE
			DO;
			CALL PRINT$HEX$WORD(MEMORY$WORD$ARG1);
			CALL PRINT$HEX$STRING(2);
			END;
		GOTO END$PASS;
		END;

	IF (TEMP$CODE$B AND 0FCH) = 0A0H THEN	/* MOV AX/L <-> MEM */
		DO;
		CALL FIND$AND$COPY(@TWO$BYT$W$IMMED$ASC,0);
		ASCII$PTR = COLUMN$1;
		IF (TEMP$CODE$B AND 1) = 0 THEN W$BIT = FALSE;
		IF (TEMP$CODE$B AND 2) = 0 THEN
			DO;
			CALL DO$REG$FIELD(0);	/* PRINT AX OR AL */
			CALL PRINT$ASCII(',');
			CALL DO$MOD$RM(6);	/* PRINT EA 16 BIT ADDRESS */
			END;
		ELSE
			DO;
			CALL DO$MOD$RM(6);	/* PRINT EA 16 BIT ADDRESS */
			CALL PRINT$ASCII(',');
			CALL DO$REG$FIELD(0);	/* PRINT AX OR AL */
			END;
		GOTO END$PASS;
		END;

	IF (TEMP$CODE$B AND 0E6H) = 06 THEN	/* PUSH/POP SEG REG */
		DO;
		CALL FIND$AND$COPY(@ONE$BYT$REG$ASC,(TEMP$CODE$B AND 1));
		ASCII$PTR = COLUMN$1;
		CALL FIND$AND$COPY(@SEG$REG$ASC,(ROR(TEMP$CODE$B,3) AND 3));
		GOTO END$PASS;
		END;

	IF (TEMP$CODE$B AND 0F4H) = 0E4H THEN		/* IN/OUT */
		DO;
		IF (TEMP$CODE$B AND 1) = 0 THEN W$BIT = FALSE;
		CALL FIND$AND$COPY(@ODDS$AND$ENDS$ASC,(ROR(TEMP$CODE$B,1) AND 1));
		ASCII$PTR = COLUMN$1;
		IF (TEMP$CODE$B AND 2) = 0 THEN		/* IN AX/L,DX OR 8 BIT */
			DO;
			CALL DO$REG$FIELD(0);		/* PRINT AX OR AL */
			CALL PRINT$ASCII(',');
			IF (TEMP$CODE$B AND 8) = 0 THEN	/* FROM 8 BIT PORT */
				DO;
				CALL PRINT$HEX$BYTE(MEMORY$ARG1);
				CALL PRINT$HEX$STRING(1);
				END;
			ELSE
				DO;
				CALL FIND$AND$COPY(@WORD$REG$ASC,2);
				END;
			END;
		ELSE
			DO;
			IF (TEMP$CODE$B AND 8) = 0 THEN	/* TO 8BIT PORT */
				DO;
				CALL PRINT$HEX$BYTE(MEMORY$ARG1);
				CALL PRINT$HEX$STRING(1);
				END;
			ELSE
				DO;
				CALL FIND$AND$COPY(@WORD$REG$ASC,2);
				END;
			CALL PRINT$ASCII(',');
			CALL DO$REG$FIELD(0);
			END;
		GOTO END$PASS;
		END;


/************************ END OF ONE BYTE CODES *************************/

/* SORT OUT TWO BYTE OPCODES */

	TEMP$CODE$W = (SHL(DOUBLE(TEMP$CODE$B),8)) + (MEMORY$ARG1);
	CALL PRINT$HEX$STRING(1);			/* ADJUST FOR WORD OPCODE */

	IF (TEMP$CODE$W AND 0F800H) = 0D800H THEN	/* ESCAPE */
		DO;
		CALL FIND$AND$COPY(@ODDS$AND$ENDS$ASC,7);
		ASCII$PTR = COLUMN$1;
		CALL DO$MOD$RM(LOW(TEMP$CODE$W));
		GOTO END$PASS;
		END;

	IF (TEMP$CODE$W AND 0FD20H) = 8C00H THEN	/* MOV REG<-> SEGR */
		DO;
		CALL FIND$AND$COPY(@TWO$BYT$W$IMMED$ASC,0);	/* MOV */
		ASCII$PTR = COLUMN$1;
		IF (TEMP$CODE$W AND 200H) = 00H
		THEN
			DO;
			CALL DO$MOD$RM(LOW(TEMP$CODE$W));
			CALL PRINT$ASCII(',');
			CALL FIND$AND$COPY(@SEG$REG$ASC,(ROR(TEMP$CODE$W,3) AND 3));
			END;
		ELSE
			DO;
			CALL FIND$AND$COPY(@SEG$REG$ASC,(ROR(TEMP$CODE$W,3) AND 3));
			CALL PRINT$ASCII(',');
			CALL DO$MOD$RM(LOW(TEMP$CODE$W));
			END;
		GOTO END$PASS;
		END;


	IF SCAN$WRD$CODES((TEMP$CODE$W AND 0FF38H),@TWO$BYT$MOD$RM$COD,6) = TRUE
	THEN
		DO;
		CALL FIND$AND$COPY(@TWO$BYT$MOD$RM$ASC,INDEX);
		ASCII$PTR = COLUMN$1;
		CALL DO$MOD$RM(LOW(TEMP$CODE$W));
		GOTO END$PASS;
		END;

	IF SCAN$WRD$CODES((TEMP$CODE$W AND 0FE38H),@TWO$BYT$MOD$RM$WRD$COD,8) = TRUE
	THEN
		DO;
		IF (TEMP$CODE$W AND 100H) = 0 THEN W$BIT = FALSE;	/* SET BYTE */
		CALL FIND$AND$COPY(@TWO$BYT$MOD$RM$WRD$ASC,INDEX);
		ASCII$PTR = COLUMN$1;
		CALL DO$MOD$RM(LOW(TEMP$CODE$W));
		GOTO END$PASS;
		END;

	IF SCAN$WRD$CODES((TEMP$CODE$W),@TWO$BYT$NOBIT$COD,2) = TRUE
	THEN
		DO;
		CALL FIND$AND$COPY(@TWO$BYT$NOBIT$ASC,INDEX);
		GOTO END$PASS;
		END;

	IF SCAN$WRD$CODES((TEMP$CODE$W AND 0FC38H),@TWO$BYT$MOD$RM$VW$COD,7) = TRUE
	THEN
		DO;
		IF (TEMP$CODE$W AND 100H) = 0 THEN W$BIT = FALSE;	/* SET BYTE */
		CALL FIND$AND$COPY(@TWO$BYT$MOD$RM$VW$ASC,INDEX);
		ASCII$PTR = COLUMN$1;
		CALL DO$MOD$RM(LOW(TEMP$CODE$W));
		CALL PRINT$ASCII(',');
		IF (TEMP$CODE$W AND 200H) = 0 THEN
			DO;
			CALL PRINT$ASCII('1');
			END;
		ELSE
			DO;
			CALL FIND$AND$COPY(@BYTE$REG$ASC,1);
			END;
		GOTO END$PASS;
		END;

	IF SCAN$WRD$CODES((TEMP$CODE$W AND 0FE38H),@TWO$BYT$W$IMMED$COD,5) = TRUE
	THEN
		DO;
		IF (TEMP$CODE$W AND 100H) = 0 THEN W$BIT = FALSE;	/* SET BYTE */
		CALL FIND$AND$COPY(@TWO$BYT$W$IMMED$ASC,INDEX);
		ASCII$PTR = COLUMN$1;
		CALL DO$MOD$RM(LOW(TEMP$CODE$W));
		CALL PRINT$ASCII(',');
		IF W$BIT = FALSE THEN
			DO;
			CALL PRINT$HEX$BYTE(MEMORY$ARG1);
			CALL PRINT$HEX$STRING(1);
			END;
		ELSE
			DO;
			CALL PRINT$HEX$WORD(MEMORY$WORD$ARG1);
			CALL PRINT$HEX$STRING(2);
			END;
		GOTO END$PASS;
		END;

	IF SCAN$WRD$CODES((TEMP$CODE$W AND 0FC38H),@TWO$BYT$SW$IMMED$COD,5) = TRUE
	THEN
		DO;
		IF (TEMP$CODE$W AND 100H) = 0 THEN W$BIT = FALSE;	/* SET BYTE */
		CALL FIND$AND$COPY(@TWO$BYT$SW$IMMED$ASC,INDEX);
		ASCII$PTR = COLUMN$1;
		CALL DO$MOD$RM(LOW(TEMP$CODE$W));
		CALL PRINT$ASCII(',');
		IF (TEMP$CODE$W AND 300H) = 100H THEN
			DO;
			CALL PRINT$HEX$WORD(MEMORY$WORD$ARG1);
			CALL PRINT$HEX$STRING(2);
			END;
		ELSE
			DO;
			CALL PRINT$HEX$BYTE(MEMORY$ARG1);
			CALL PRINT$HEX$STRING(1);
			END;
		GOTO END$PASS;
		END;


ERROR$PASS:

	CALL FIND$AND$COPY(@ERROR$MESS,0);

END$PASS:

	BUFFER(ASCII$PTR) = 0;		/* APPEND TERMINATING CHAR */
	I = 0;
		DO WHILE (BUFFER(I)) <> 0;	/* PRINT BUFFER UNTIL NUL FOUND */
		CALL SIO$OUT$CHAR(BUFFER(I));
		I = I + 1;
		END;
	TEMP$PAGE = TEMP$PAGE - 1;
	IF TEMP$PAGE = 0 THEN
		DO;
			DO I=1 TO 3;
			CALL SIO$OUT$CHAR(ASLF);	/* 3 LINE FEEDS */
			END;
		TEMP$PAGE = LOW(PAGE$LEN);
		CALL SIO$GET$CHAR;		/* PAUSE */
		END;
	END;
	END FCMD;

/*******************************************************************/

FCMD$8086:

PROCEDURE;

	DO;
	CALL SIO$TEST$WORD$MODE;		/* ALLOWS A SPACE BETWEEN 'F' & ADDR */
	CALL SIO$GET$ADDR(@ARG1,CS);
	IF CHAR <> ',' THEN GOTO ERROR;
	CALL SIO$GET$CHAR;
	END$OFF = SIO$GET$WORD;
	PAGE$LEN = 20;						/* SET DEFAULT PAGE LENGTH */
	IF END$OFF < ARG1.OFF THEN GOTO ERROR;
	IF CHAR = ',' THEN					/* GET AND RESET PAGE LENGTH */
		DO;
		CALL SIO$GET$CHAR;
		PAGE$LEN = SIO$GET$WORD;
		IF PAGE$LEN > 200 THEN			/* PAGE LENGTH TOO BIG CORRECT */
			DO;
			PAGE$LEN = 200;
			END;
		END;
	IF CHAR <> ASCR THEN GOTO ERROR;	/* EXIT TO MAIN COMMAND ROUTINE */
	TEMP$PAGE = LOW(PAGE$LEN);

	CALL FCMD;	/* GO DO THE WORK */

	END;

END FCMD$8086;
