Metropoli BBS
VIEWER: edcom42.a86 MODE: TEXT (CP437)
;EDCOM42 WRITTEN BY DOUG COX, OCTOBER 1987, APRIL 1988, JUNE 1988,
;NOVEMBER AND DECEMBER, 1989, USING THE SHAREWARE ASSEMBLER, A86
CODE SEGMENT
  JMP MAIN
	DB ' (c)1989 by Doug Cox '
EXPLAIN DB 'Type Edcom42 Filename to view/edit Filename$'
NOFILE	DB ' not found...$'
	DB 8 DUP ('Stack ')
STACKIT DB 'SP'
DISASS	DB 0
	DB '('
SCRNATTRIB DB 017
TOPATTRIB DB 074
MNEMATTRIB DB 078
INSTRATTRIB DB 01F
CHARATTRIB DB 067
HEXATTRIB DB 047
	DB ')'
TOPLINE DB ' CURSOR LOCATION:        CONTENTS:       '
FIND?	DB 'FIND:        '
JUMP?	DB 'JUMP TO:     '
SEARCH	DB ' SEARCHING...'
HELP?	DB ' (F1 FOR HELP)     '
CHARS	DB ' EDITING CHARS'
HEXADEC DB '  EDITING HEX  '
ESCMSG	DB 'ESC or ^KQ : EXIT                    ^KX or ^KD or ^KS : EXIT & save changes',0
	DB 0,'F2 thru F10 : toggle between',0
BLANK	DB '                 1. disable edit capability',0
	DB '                 2. enable edit capability of typeable chars only',0
	DB '                 3. enable edit capability of any character (in hexadecimal)',0
	DB 0,'    Insert or Delete : toggle assembly language translation on & off',0
	DB 0,'Arrow keys or ^S ^E ^X ^D : move cursor    ^W : scroll up   ^Z : scroll down',0
	DB 0,'PgDn or ^C : next screen                   ^PgDn or ^QC : end of file',0
	DB 0,'PgUp or ^R : previous screen               ^PgUp or ^QR : beginning of file',0
	DB 0,'Home or ^QS: left end of line              ^Home or ^QE : top of screen',0
	DB 0,'End  or ^QD: right end of line             ^End  or ^QX : bottom of screen',0
	DB 0,'TAB  or ^F : 10 right                      Shift-TAB or ^A : 10 left',0
	DB 0,'^QF : find hexadecimal or ASCII chars      ^L : continue search',0
	DB ' (examples: FIND: 07 7F ED   FIND: 077FED   FIND: ',027,'and the',027
	DB '   FIND: "can',027,'t")',0
	DB 0,'^J : jump to hexadecimal address in file               [ANY KEY TO RETURN...]'

RUTINES DW L00,L01,L02,L03,L04,L05,L06,L06,L00,L01,L02,L03,L04,L05,L0E,RTN ;0
	DW L00,L01,L02,L02,L04,L05,L16,L16,L00,L01,L02,L03,L04,L05,L1E,L1E ;1
	DW L00,L01,L02,L03,L04,L05,RTN,RTN,L00,L01,L02,L03,L04,L05,RTN,RTN ;2
	DW L00,L01,L02,L03,L04,L05,RTN,RTN,L00,L01,L02,L03,L04,L05,RTN,RTN ;3
	DW L40,L41,L42,L43,L44,L45,L46,L47,L40,L41,L42,L43,L44,L45,L46,L47 ;4
	DW L40,L41,L42,L43,L44,L45,L46,L47,L40,L41,L42,L43,L44,L45,L46,L47 ;5
	DW RTN,RTN,RTN,RTN,RTN,RTN,RTN,RTN,RTN,RTN,RTN,RTN,RTN,RTN,RTN,RTN ;6
	DW L70,L70,L70,L70,L70,L70,L70,L70,L70,L70,L70,L70,L70,L70,L70,L70 ;7
	DW L80,L81,RTN,L83,L00,L01,L00,L01,L00,L01,L02,L03,L8C,L03,L8E,L01 ;8
	DW RTN,L91,L92,L93,L94,L95,L96,L97,RTN,RTN,L9A,RTN,RTN,RTN,RTN,RTN ;9
	DW LA0,LA1,LA2,LA3,LA4,LA5,LA4,LA5,L04,L05,LA4,LA5,LA4,LA5,LA4,LA5 ;A
	DW LB0,LB1,LB2,LB3,LB4,LB5,LB6,LB7,LB8,LB9,LBA,LBB,LBC,LBD,LBE,LBF ;B
	DW RTN,RTN,LCA,RTN,LC4,LC4,LC6,LC7,RTN,RTN,LCA,RTN,RTN,LCD,RTN,RTN ;C
	DW LD0,LD1,LD2,LD3,RTN,RTN,RTN,RTN,RTN,RTN,RTN,RTN,RTN,RTN,RTN,RTN ;D
	DW L70,L70,L70,L70,LE4,LE5,LE6,LE7,LE8,LE8,L9A,LEB,LEC,LED,LEE,LEF ;E
	DW RTN,RTN,LF2,LF3,RTN,RTN,LF6,LF7,RTN,RTN,RTN,RTN,RTN,RTN,LFE,LFF ;F

EVEN
HANDLE	DW 0
BUFOFF	DW 0
BUFSEG	DW 0
FILEBEG DW 0
FTOPLEF DW 0
TOPLEF	DW 0
LTOPLEF DW 0
FILENDO DW 0
FILENDS DW 0
LASTCOL DW 0
FILSIZO DW 0
FILSIZS DW 0
TEMPFIL DW 0
BEGIN	DW 0
CURLOC	DW 0
SCRNCUR DW 0
OLDSCUR DW 0
ABSLOC1 DW 0
ABSLOC2 DW 0
SAVES	DW 0
HEADSIZ DW 0
SAVEBX	DW 0
STRCNT	DW 0
OLDCUR	DW 0
CURSHPE DW 0
CURPTR	DW 0
BYTE2	DB 0
ISEXE	DB 0
EDFLGS	DB 4
MODE	DB 0
FINDSTR DB 19 DUP(' ')

REGB DB 'ALCLDLBLAHCHDHBH'
REGW DB 'AXCXDXBXSPBPSIDI'
SEGS DB 'ESCSSSDS'
BW DB ?
ADDR DB '[BX+SI] [BX+DI] [BP+SI] [BP+DI] [SI]    [DI]    [BP]    [BX]    '

__	DB ' '
_AAA	DB 'AAA '
_AAD	DB 'AAD '
_AAM	DB 'AAM '
_AAS	DB 'AAS '
_ADC	DB 'ADC '
_ADD	DB 'ADD '
_AND	DB 'AND '
_CALL	DB 'CALL '
_CBW	DB 'CBW '
_CLC	DB 'CLC '
_CLD	DB 'CLD '
_CLI	DB 'CLI '
_CMC	DB 'CMC '
_CMP	DB 'CMP '
_CMPS	DB 'CMPS '
_CS	DB 'CS '
_CWD	DB 'CWD '
_DAA	DB 'DAA '
_DAS	DB 'DAS '
_DEC	DB 'DEC '
_DIV	DB 'DIV '
_ES	DB 'ES '
_HLT	DB 'HLT '
_IDIV	DB 'IDIV '
_IMUL	DB 'IMUL '
_IN	DB 'IN '
_INC	DB 'INC '
_INT	DB 'INT '
_INT3	DB 'INT_3 '
_INTO	DB 'INTO '
_IRET	DB 'IRET '
_JA	DB 'JA '
_JB	DB 'JB '
_JBE	DB 'JBE '
_JCXZ	DB 'JCXZ '
_JG	DB 'JG '
_JGE	DB 'JGE '
_JL	DB 'JL '
_JLE	DB 'JLE '
_JMP	DB 'JMP '
_JNC	DB 'JNC '
_JNO	DB 'JNO '
_JNS	DB 'JNS '
_JNZ	DB 'JNZ '
_JO	DB 'JO '
_JP	DB 'JP '
_JPE	DB 'JPE '
_JPO	DB 'JPO '
_JS	DB 'JS '
_JZ	DB 'JZ '
_LAHF	DB 'LAHF '
_LDS	DB 'LDS '
_LEA	DB 'LEA '
_LES	DB 'LES '
_LOCK	DB 'LOCK '
_LODS	DB 'LODS '
_LOOP	DB 'LOOP '
_LOOPNZ DB 'LOOPNZ '
_LOOPZ	DB 'LOOPZ '
_MOV	DB 'MOV '
_MOVS	DB 'MOVS '
_MUL	DB 'MUL '
_NEG	DB 'NEG '
_NOP	DB 'NOP '
_NOT	DB 'NOT '
_OR	DB 'OR '
_OUT	DB 'OUT '
_POP	DB 'POP '
_POPF	DB 'POPF '
_PUSH	DB 'PUSH '
_PUSHF	DB 'PUSHF '
_RCL	DB 'RCL '
_RCR	DB 'RCR '
_REP	DB 'REP '
_REPNZ	DB 'REPNZ '
_RET	DB 'RET '
_RETF	DB 'RETF '
_ROL	DB 'ROL '
_ROR	DB 'ROR '
_SAHF	DB 'SAHF '
_SAR	DB 'SAR '
_SBB	DB 'SBB '
_SCAS	DB 'SCAS '
_SHL	DB 'SHL '
_SHR	DB 'SHR '
_SS	DB 'SS '
_STC	DB 'STC '
_STD	DB 'STD '
_STI	DB 'STI '
_STOS	DB 'STOS '
_SUB	DB 'SUB '
_TEST	DB 'TEST '
_WAIT	DB 'WAIT '
_XCHG	DB 'XCHG '
_XLAT	DB 'XLAT '
_XOR	DB 'XOR '

INSTRPTR DW _ADD,_ADD,_ADD,_ADD,_ADD,_ADD,_PUSH,_POP		;0
	DW _OR,_OR,_OR,_OR,_OR,_OR,_PUSH,__
	DW _ADC,_ADC,_ADC,_ADC,_ADC,_ADC,_PUSH,_POP		;1
	DW _SBB,_SBB,_SBB,_SBB,_SBB,_SBB,_PUSH,_POP
	DW _AND,_AND,_AND,_AND,_AND,_AND,_ES,_DAA		;2
	DW _SUB,_SUB,_SUB,_SUB,_SUB,_SUB,_CS,_DAS
	DW _XOR,_XOR,_XOR,_XOR,_XOR,_XOR,_SS,_AAA		;3
	DW _CMP,_CMP,_CMP,_CMP,_CMP,_CMP,_CS,_AAS
	DW _INC,_INC,_INC,_INC,_INC,_INC,_INC,_INC		;4
	DW _DEC,_DEC,_DEC,_DEC,_DEC,_DEC,_DEC,_DEC
	DW _PUSH,_PUSH,_PUSH,_PUSH,_PUSH,_PUSH,_PUSH,_PUSH	;5
	DW _POP,_POP,_POP,_POP,_POP,_POP,_POP,_POP
	DW __,__,__,__,__,__,__,__				;6
	DW __,__,__,__,__,__,__,__
	DW _JO,_JNO,_JB,_JNC,_JZ,_JNZ,_JBE,_JA			;7
	DW _JS,_JNS,_JP,_JPO,_JL,_JGE,_JLE,_JG
	DW __,__,__,__,_TEST,_TEST,_XCHG,_XCHG			;8
	DW _MOV,_MOV,_MOV,_MOV,_MOV,_LEA,_MOV,_POP
	DW _NOP,_XCHG,_XCHG,_XCHG,_XCHG,_XCHG,_XCHG,_XCHG	;9
	DW _CBW,_CWD,_CALL,_WAIT,_PUSHF,_POPF,_SAHF,_LAHF
	DW _MOV,_MOV,_MOV,_MOV,_MOVS,_MOVS,_CMPS,_CMPS		;A
	DW _TEST,_TEST,_STOS,_STOS,_LODS,_LODS,_SCAS,_SCAS
	DW _MOV,_MOV,_MOV,_MOV,_MOV,_MOV,_MOV,_MOV		;B
	DW _MOV,_MOV,_MOV,_MOV,_MOV,_MOV,_MOV,_MOV
	DW __,__,_RET,_RET,_LES,_LDS,_MOV,_MOV			;C
	DW __,__,_RETF,_RETF,_INT3,_INT,_INTO,_IRET
	DW __,__,__,__,_AAM,_AAD,__,_XLAT			;D
	DW __,__,__,__,__,__,__,__
	DW _LOOPNZ,_LOOPZ,_LOOP,_JCXZ,_IN,_IN,_OUT,_OUT 	;E
	DW _CALL,_JMP,_JMP,_JMP,_IN,_IN,_OUT,_OUT
	DW _LOCK,__,_REPNZ,_REP,_HLT,_CMC,__,__ 		;F
	DW _CLC,_STC,_CLI,_STI,_CLD,_STD,__,__

IMMED DW _ADD,_OR,_ADC,_SBB,_AND,_SUB,_XOR,_CMP
SHIFT DW _ROL,_ROR,_RCL,_RCR,_SHL,_SHR,__,_SAR
GRP1 DW _TEST,__,_NOT,_NEG,_MUL,_IMUL,_DIV,_IDIV
GRP2 DW _INC,_DEC,_CALL,_CALL,_JMP,_JMP,_PUSH,__
ISGGPTRS DW IMMED,SHIFT,GRP1,GRP2

MAIN:
;GET MAX FILE SIZE
  MOV AH,04A		;FUNCTION TO MODIFY EXTRA MEMORY
  MOV BX,0FFFF		;LARGE ENOUGH TO MAKE FUNCTION FAIL (& GIVE AVAIL SPACE)
  INT 021
  MOV AX,BX		;AVAILABLE MEMORY IN PARAGRAPHS (16 BYTES/PARAGRAPH)
  ADD AX,0FB		;EXTRA SPACE USED AT END OF THIS PROGRAM (IN PARAGRAPHS)
  SUB DX,DX
  MOV BX,16
  MUL BX		;TO GET FREE MEMORY SPACE IN BYTES
  MOV FILSIZS,DX	;TEMPORARY
  MOV FILSIZO,AX	;DITTO

;PREPARE TO READ FILE TO MEMORY BUFFER
  MOV AL,B[080] 	;DTA
  SUB AH,AH
  OR AL,AL
  JNZ CONTINU		;IF FILENAME WAS ON COMMAND LINE
  MOV DX,OFFSET EXPLAIN
  MOV AH,9
  INT 021
  MOV AX,04C00
  INT 021
CONTINU:
  MOV CX,AX		;SIZE OF FILENAME
  ADD AX,081
  MOV SI,AX
  MOV [SI],AH		;PUT ASCIIZ 0 AT END OF STRING
;CHECK FOR .COM OR .EXE FILE
  MOV DI,082
  MOV AL,'.'
  REPNE SCASB
  JCXZ NOEXE
  CMP W[DI],'OC'
  JNZ NOTCOM
  CMP B[DI+2],'M'
  JNZ NOTCOM
  MOV W[BEGIN],0100	;BEGINNING ADDRESS OF .COM FILES IS 0100
  JMP SHORT NOEXE
NOTCOM:
  CMP W[DI],'XE'
  JNZ NOEXE
  CMP B[DI+2],'E'
  JNZ NOEXE
  MOV B[ISEXE],0FF	;FLAG
NOEXE:
  MOV DX,082
  MOV AX,03D02		;OPEN FUNCTION (FOR READ/WRITE)
  INT 021
  IF C JMP NOTHERE
  MOV HANDLE,AX

;MOVE STACK & CHECK SCREEN
  MOV AX,OFFSET STACKIT
  MOV SP,AX
  MOV AH,0F		;FUNCTION TO CHECK SCREEN MODE
  INT 010
  MOV MODE,AL		;SAVE IT

;SAVE OLD CURSOR LOCATION
  CALL GETCUR
  DEC DH
  MOV OLDCUR,DX 	;ROW IN DH / COL IN DL
  MOV CURSHPE,CX	;STARTING & ENDING LINE FOR CURSOR

;SAVE OLD SCREEN
  MOV DI,OLDSCR
  MOV AX,0B000		;VIDEO MEMORY ADDRESS
  CMP MODE,7
  IF NZ MOV AX,0B800	;IF CGA DISPLAY
  MOV DS,AX
  SUB SI,SI
  MOV CX,2000
  REP MOVSW
  MOV ES,AX
  MOV AX,CS
  MOV DS,AX

;GET FILE SIZE
  MOV AX,04202
  MOV BX,HANDLE
  SUB CX,CX
  SUB DX,DX
  INT 021		;FILE SIZE IN DX:AX (E.G. 1:2345H)
  IF C JMP EXIT
;CHECK IF IT WILL FIT IN AVAILABLE MEMORY
  CMP DX,FILSIZS
  JC >L1
  CMP AX,FILSIZO
  IF NC INT 020 	;IF FILE WOULDN'T FIT
L1:
  MOV FILSIZS,DX
  MOV FILSIZO,AX

;RESET FILE POINTER TO START OF FILE
  MOV AX,04200
  MOV BX,HANDLE
  SUB CX,CX
  SUB DX,DX
  INT 021

;GET NEW BUFFER SEGMENT ADDRESS & MEMORY ADDR THAT GOES AT TOP LEFT OF SCREEN
  MOV AX,PREBUF 	;AT END OF THIS CODE (PAST ANOTHER BUFFER)
  MOV CL,4
  SHR AX,CL		;CHANGE OFFSET-TYPE ADDRESS TO SEGMENT-TYPE ADDRESS
  MOV DX,DS
  ADD AX,DX
  MOV FILEBEG,AX	;NEW SEGMENT ADDRESS BEGINS AT BUFFER
  MOV BX,AX
  SHL AX,CL		;SHIFT 1 NIBBLE LEFT FOR OFFSET ADDR
  ROL BX,CL		;MOVE LEFT NIBBLE TO RIGHT
  AND BX,0F		;CLEAR ALL BUT RIGHT-MOST NIBBLE
  MOV BUFSEG,BX 	;FOR USE IN FIND
  MOV BUFOFF,AX 	;DITTO

;READ FILE INTO MEMORY BUFFER
  MOV BX,HANDLE
  MOV BP,FILSIZS
  MOV AX,FILSIZO
  MOV DX,FILEBEG
READFILE:
  MOV TEMPFIL,AX
  MOV CX,0FFF0
  OR BP,BP
  IF Z MOV CX,AX	;IF ONLY 1 SEGMENT TO READ
  MOV DS,DX
  PUSH DX
  SUB DX,DX
  MOV AH,03F		;FUNCTION TO READ FILE
  INT 021
  MOV DX,CS
  MOV DS,DX
  POP DX
  ADD DX,0FFF		;TO INCREMENT DS
  IF C JMP EXIT
  OR AX,AX
  IF Z JMP EXIT
  MOV AX,TEMPFIL
  SUB AX,0FFF0
  SBB BP,0
  JNS READFILE		;IF IT DIDN'T DECREMENT LESS THAN 0

  CALL DISPLTOP 	;PUT TOP LINE ON SCREEN
  MOV AH,1		;FUNCTION TO CHANGE CURSOR SHAPE
  MOV CX,7		;TOP & BOTTOM ROW OF CURSOR
  INT 010

;PUT BORDER AROUND SCREEN
  MOV AH,0B
  MOV BL,SCRNATTRIB
  MOV CL,4
  SHR BX,CL
  AND BX,0F
  INT 010

;CHECK FOR .EXE FILE
  MOV SI,FILEBEG	;BEGINNING OF FILE IN MEMORY
  CMP B[ISEXE],0FF
  JNZ NOTEXE
  MOV DS,SI
  CMP W[0],05A4D	;'MZ' IS AT BEGINNING OF ALL .EXE FILES
  JNZ NOTEXE
  MOV AX,W[0008]	;WHERE LENGTH OF HEADER IS LOCATED
  ADD SI,AX		;MOVE PAST HEADER
  MOV CL,4
  SHL AX,CL
  CS MOV HEADSIZ,AX
  MOV AX,W[0016]	;CODE SEGMENT DISPLACEMENT
  SUB BX,BX
  SHL AX,CL		;CHANGE FROM SEGMENT TO OFFSET
  ADC BX,0		;SEGMENT
  ADD AX,W[0014]	;INSTRUCTION POINTER OFFSET
  ADC BX,0
  MOV DX,CS
  MOV DS,DX
  MOV SAVES,AX		;OFFSET
  MOV SAVEBX,BX 	;SEGMENT
NOTEXE:
  MOV AX,CS
  MOV DS,AX
  MOV FTOPLEF,SI

;GET FILE END ADDRESS
  MOV BX,BUFSEG
  MOV AX,BUFOFF
  ADD AX,FILSIZO
  ADC BX,FILSIZS
  MOV FILENDS,BX
  MOV FILENDO,AX

;GET LAST COLUMN
  MOV DX,FILSIZS
  MOV AX,FILSIZO
  SUB AX,1
  SBB DX,0
  SUB AX,HEADSIZ
  SBB DX,0
  MOV CX,80
  DIV CX		;DX:AX/CX (TO GET REMAINDER IN DX)
  MOV LASTCOL,DX	;COLUMNS ON LAST ROW

;GET LAST TOPLEF
  MOV AX,FILENDO
  MOV BX,FILENDS
  SUB FILENDO,1
  SBB FILENDS,0
  SUB AX,DX		;TO BEGINNING OF LAST LINE
  SBB BX,0
  SUB AX,1840		;TO TOP LEFT OF SCREEN (23*80)
  SBB BX,0
  MOV CL,4
  SHR AX,CL
  ROR BX,CL		;PUT RIGHT NIBBLE ON LEFT
  ADD AX,BX
  MOV LTOPLEF,AX
;JUMP TO BEGINNING OF CODE IF .EXE FILE
  MOV DI,SAVES
  OR DI,DI
  JZ FILETOP
  MOV BX,SAVEBX
  JMP ITSEXE

;JUMPED TO WITH ^PGUP
FILETOP:
  MOV SI,FTOPLEF
  MOV TOPLEF,SI 	;BEGINNING OF SEGMENT IS ALWAYS AT TOPLEF
  MOV CURPTR,0		;CURSOR OFFSET LOCATION
  MOV DX,0100		;ROW 1/COLUMN 0
  CALL MOVCUR		;INITIALIZE CURSOR AT TOP LEFT

;DISPLAY FILE
NEWSCRN:
  MOV AH,SCRNATTRIB
  CMP MODE,7		;MONOCHROME
  IF Z MOV AH,7
  SUB SI,SI		;OFFSET OF FILE TO PUT ON SCREEN
  MOV DI,160		;TOP LEFT OF SCREEN
  MOV DX,TOPLEF
  CMP DX,LTOPLEF
  JNC ATEND
  MOV CX,1920		;80*24 SCREEN
  CMP DISASS,0
  MOV DS,DX		;TOPLEF IS ALSO DATA SEGMENT BEGINNING
  JZ DONTSHOALL
  CALL MOVIT		;LODSB, STOSW, LOOP
  JMP SHORT NEW2
DONTSHOALL:
  CALL MOVIT2
  JMP SHORT NEW2
ATEND:
  MOV BX,FILENDO
  MOV DS,DX		;TOPLEF
  MOV CL,4
  SHL DX,CL		;TO GET OFFSET VALUE OF TOPLEF
  NEG DX
  ADD BX,DX		;FILENDO-TOPLEF
  INC BX
  MOV CX,BX
  CS CMP DISASS,0
  JZ DONTSHOALL2
  CALL MOVIT		;PUT LAST PAGE OF FILE ON SCREEN
  JMP SHORT >L1
DONTSHOALL2:
  CALL MOVIT2
L1:
  MOV DX,CS
  MOV DS,DX		;PUT DATA SEG BACK
  MOV CX,1920		;80*24 SCREEN (NOT COUNTING TOP LINE)
  SUB CX,BX		;SCREEN SIZE - (FILEND-TOPLEF)
  MOV AH,SCRNATTRIB
  CMP MODE,7		;MONOCHROME
  IF Z MOV AH,7
  MOV AL,' '
  REP STOSW		;PUT CX BLANKS TO END OF SCREEN
NEW2:
  MOV DX,CS
  MOV DS,DX		;PUT DATA SEG BACK

;PUT CURSOR LOCATION & CONTENTS AT SCREEN TOP
  MOV DX,TOPLEF ;DATA SEGMENT
  SUB DX,FTOPLEF	;TO MAKE TOPLEF RELATIVE TO FTOPLEF
  MOV BX,DX		;FOR FIRST BIN2HEX CALL
  MOV CL,4
  SHL DX,CL
  ADD DX,CURPTR 	;OFFSET ADDR
  IF C ADD BX,01000	;INCREMENT 5TH BYTE
  ADD DX,BEGIN
  IF C ADD BX,01000
  MOV ABSLOC1,BX
  MOV ABSLOC2,DX
  MOV DI,36		;LOCATION ON SCREEN
  MOV CH,1		;FOR COUNT
  CALL BIN2HEX		;SHOW 5TH BYTE OF LOCATION
  MOV BX,DX
  MOV CH,4
  CALL BIN2HEX		;SHOW OTHER 4 BYTES OF LOCATION

  MOV SI,CURPTR 	;CURSOR LOCATION IN MEMORY
  MOV DS,TOPLEF
  MOV BH,[SI]		;CONTENTS
  MOV CX,CS
  MOV DS,CX
  MOV DI,70		;SCREEN LOC
  MOV CH,2		;2 CHARS
  CALL BIN2HEX

DIS:
  MOV AH,MNEMATTRIB
  CMP MODE,7
  IF Z MOV AH,070
  CMP EDFLGS,4
  JNZ WATE		;IF EDITING CHARS OR HEX
  MOV AL,' '
  MOV DI,78
  MOV CX,25
  REP STOSW		;CLEAR PREVIOUS INSTRUCTIONS
  CMP DISASS,0FF
  JNZ WATE		;IF NOT SHOWING DISASSEMBLY

  MOV DX,CURLOC 	;CURSOR LOCATION ON SCREEN
  SHL DL,1		;DOUBLE ROW NUMBER
  MOV AL,DH		;COLUMN
  MOV CL,160
  MUL CL
  SUB DH,DH
  ADD AX,DX
  INC AX		;TO WHERE CHAR ATTRIBUTE GOES
  MOV DI,AX
  MOV OLDSCUR,AX	;OLD SCREEN CURSOR LOCATION
  MOV SCRNCUR,AX
  MOV AL,INSTRATTRIB
  CMP MODE,7
  IF Z MOV AL,070
  ES MOV B[DI],AL	;HILITE FIRST INSTRUCTION BYTE
  ADD SCRNCUR,2
  MOV DI,82
DIS2:
  MOV BX,OFFSET INSTRPTR
  MOV DS,TOPLEF
  LODSB
  MOV CX,CS
  MOV DS,CX
  SUB AH,AH
  SHL AX,1
  PUSH SI,AX
  ADD BX,AX
  MOV SI,[BX]		;LOCATION OF FIRST INSTRUCTION IN INSTRPTR
  MOV AH,MNEMATTRIB
  CMP MODE,7
  IF Z MOV AH,070
INSTRLP:
  LODSB
  STOSW
  CMP AL,' '
  JNZ INSTRLP
  POP AX,SI
  MOV BX,OFFSET RUTINES
  ADD BX,AX
  CALL [BX]

;READ KEYBOARD
WATE:
  SUB AH,AH		;FUNCTION TO READ KEYBOARD
  INT 016		;PROGRAM STAYS HERE, MOSTLY
  OR AL,AL
  JZ  EXTENDED_CODE
  CMP AL,' '
  JL CTRL_CODE
  JMP INPUT

CTRL_CODE:
  CALL CASE	;TO JUMP TO FOLLOWING SUBROUTINES
  DB 17 	;NUMBER OF FOLLOWING SUBROUTINES
  DB 10 	;^J
  DW JUMP
  DB 12 	;^L
  DW AGAIN
  DB 27 	;ESC
  DW EXIT
  DB 18 	;^R
  DW PREV
  DB 3		;^C
  DW NEXT
  DB 5		;^E
  DW CURUP
  DB 24 	;^X
  DW CURDN
  DB 19 	;^S
  DW CURLFT
  DB 4		;^D
  DW CURRT
  DB 23 	;^W
  DW UP
  DB 26 	;^Z
  DW DOWN
  DB 6		;^F
  DW MOVRT
  DB 1		;^A
  DW MOVLFT
  DB 9		;TAB
  DW MOVRT
  DB 11 	;^K
  DW KMENU
  DB 17 	;^Q
  DW QMENU
  DB 13 	;ENTER
  DW INPUT
  DW WATE

EXTENDED_CODE:
  MOV AL,AH
  CALL CASE
  DB 27 	;NUMBER OF SUBROUTINES TO CHECK
  DB 59 	;F1
  DW EMENU
  DB 60 	;F2
  DW EDIT
  DB 61 	;F3
  DW EDIT
  DB 62 	;F4
  DW EDIT
  DB 63
  DW EDIT
  DB 64
  DW EDIT
  DB 65
  DW EDIT
  DB 66
  DW EDIT
  DB 67
  DW EDIT
  DB 68 	;F10
  DW EDIT
  DB 71 	;HOME
  DW LFTSIDE
  DB 79 	;END
  DW RTSIDE
  DB 73 	;PGUP
  DW PREV
  DB 81 	;PGDN
  DW NEXT
  DB 72 	;UP ARROW
  DW CURUP
  DB 80 	;DOWN ARROW
  DW CURDN
  DB 75 	;LEFT ARROW
  DW CURLFT
  DB 77 	;RIGHT ARROW
  DW CURRT
  DB 116	;^RIGHT ARROW
  DW MOVRT
  DB 115	;^LEFT ARROW
  DW MOVLFT
  DB 132	;^PGUP
  DW FILETOP
  DB 118	;^PGDN
  DW GOEND
  DB 119	;^HOME
  DW SCRTOP
  DB 117	;^END
  DW SCRBOT
  DB 15 	;SHIFT-TAB
  DW MOVLFT
  DB 82 	;INSERT
  DW TOGGLEDIS
  DB 83 	;DELETE
  DW TOGGLEDIS
  DW WATE	;GO THERE IF NOT ONE OF ABOVE

QMENU:
  MOV B ES:[122],'^'
  MOV B ES:[124],'Q'
  SUB AH,AH
  INT 016H
  MOV B ES:[122],' '
  MOV B ES:[124],' '
  AND AL,01F
  CALL CASE
  DB 7		;NUMBER OF FOLLOWING SUBROUTINES
  DB 18 	;^R
  DW FILETOP
  DB 3		;^C
  DW GOEND
  DB 5		;^E
  DW SCRTOP
  DB 24 	;^X
  DW SCRBOT
  DB 19 	;^S
  DW LFTSIDE
  DB 4		;^D
  DW RTSIDE
  DB 6		;^F
  DW FIND
  DW WATE

KMENU:
  MOV B ES:[122],'^'
  MOV B ES:[124],'K'
  SUB AH,AH
  INT 016
  MOV B ES:[122],' '
  MOV B ES:[124],' '
  AND AL,01F
  CALL CASE
  DB 4
  DB 17 	;^Q
  DW EXIT
  DB 24 	;^X
  DW WRITE
  DB 4		;^D
  DW WRITE
  DB 19 	;^S
  DW WRITE
  DW WATE

INPUT:
  CMP DISASS,0FF
  JNZ NOJUMP		;IF NOT SHOWING DISASSEMBLY
  CMP EDFLGS,4
  JNZ NOJUMP		;IF EDITING CHARS OR HEX
  MOV CX,SCRNCUR
  SUB CX,OLDSCUR
  JZ NOJUMP
  SHR CX,1
NEXTINSTR:
  PUSH CX
  CALL RTCUR		;MOVE CURSOR RIGHT TO NEXT INSTRUCTION
  POP CX
  LOOP NEXTINSTR
  JMP NEWSCRN
NOJUMP:
  CMP EDFLGS,2
  JNZ HEXINPUT
  MOV SI,CURPTR
  MOV DS,TOPLEF
  CMP B[SI],' '
  JB NOTHEX
  CMP B[SI],'~'
  JA NOTHEX
  MOV [SI],AL		;PUT INPUT IN MEMORY
  MOV DX,CS
  MOV DS,DX
  MOV AH,0AH		;FUNCTION TO WRITE CHAR TO SCREEN
  SUB BH,BH		;SCREEN PAGE
  MOV CX,1
  INT 010
  JMP CURRT

HEXINPUT:
  CMP EDFLGS,3
  IF NZ JMP WATE
  MOV BL,AL		;SAVE INPUT
  CALL HEX2BIN
  JC NOTHEX		;IF NOT GOOD HEX INPUT
  MOV DL,AL		;SAVE BINARY REPRESENTATION
  CMP BL,'a'
  IF NC SUB BL,020	;MAKE LETTERS UPPERCASE
  ES MOV [70],BL	;DISPLAY FIRST HEX INPUT
  ES MOV B[72],'_'
  SUB AH,AH
  INT 016
  MOV BH,AL		;SAVE SECOND HEX INPUT
  CALL HEX2BIN
  JC NOTHEX
  MOV DH,AL		;SAVE SECOND BINARY REPRESENTATION
  ES MOV [72],BH	;DISPLAY SECOND INPUT
  MOV CL,4
  SHL DL,CL
  OR DL,DH
  MOV SI,CURPTR
  MOV DS,TOPLEF
  MOV [SI],DL		;PUT REVISION IN MEMORY
  MOV CX,CS
  MOV DS,CX
  JMP NEWSCRN

NOTHEX:
  MOV DX,CS
  MOV DS,DX
  MOV AL,7		;BEEP
  MOV AH,0E		;FUNCTION TO WRITE CHAR
  SUB BH,BH		;PAGE
  MOV CX,1
  INT 010
  JMP NEWSCRN

TOGGLEDIS:
  XOR DISASS,0FF
  JMP NEWSCRN

EDIT:
  CALL DISPLTOP
  INC EDFLGS
  CMP EDFLGS,5
  IF Z MOV EDFLGS,2
  CMP EDFLGS,2
  JZ EDCHARS
  CMP EDFLGS,3
  JZ EDHEX
UNEDIT:
  MOV EDFLGS,4
  MOV SI,OFFSET HELP?
  MOV AH,TOPATTRIB
  JMP SHORT SHOIT
EDCHARS:
  MOV SI,OFFSET CHARS
  MOV AH,CHARATTRIB
  JMP SHORT PRESHOIT
EDHEX:
  MOV SI,OFFSET HEXADEC
  MOV AH,HEXATTRIB
PRESHOIT:
  PUSH AX,SI
  MOV AH,TOPATTRIB
  CMP MODE,7
  IF Z MOV AH,070
  MOV SI,OFFSET HELP?
  MOV DI,82
  MOV CX,20
  CALL MOVIT
  POP SI,AX
SHOIT:
  CMP MODE,7
  IF Z MOV AH,070
  MOV DI,130
  MOV CX,15
  CALL MOVIT
  JMP NEWSCRN

;F1
EMENU:
  MOV SI,OFFSET ESCMSG
EMENU2:
  CALL HIDECUR
  CALL MENWRT
  CMP AL,11		;^K
  JNZ NOTCTRLK
  MOV B ES:[442],'^'
  MOV B ES:[444],'K'
  SUB AH,AH
  INT 016
  MOV B ES:[442],' '
  MOV B ES:[444],' '
  AND AL,01F
  CMP AL,17		;^Q
  IF Z JMP EXIT
  CMP AL,24		;^X
  IF Z JMP WRITE
  CMP AL,4		;^D
  IF Z JMP WRITE
  CMP AL,19		;^S
  IF Z JMP WRITE
NOTCTRLK:
  PUSH AX
  MOV DX,CURLOC
  CALL MOVCUR
  POP AX
  CMP AX,03C00		;F2
  JB >L1
  CMP AX,04400		;F10
  IF BE JMP EDIT
L1:
  PUSH AX
  CALL DISPLTOP
  POP AX
  CMP AX,05200		;INSERT
  IF Z XOR DISASS,0FF
  CMP AX,05300		;DELETE
  IF Z XOR DISASS,0FF
  CMP EDFLGS,2
  IF Z JMP EDCHARS
  CMP EDFLGS,3
  IF Z JMP EDHEX
  JMP NEWSCRN

;***CURSOR MOVEMENT***

;^HOME
SCRTOP:
  MOV DX,CURLOC
  MOV AL,80
  MUL DH
  SUB CURPTR,AX
  ADD CURPTR,80 	;BECAUSE TOP ROW HERE IS 1 NOT 0
  MOV DH,1		;TOP ROW
  CALL MOVCUR
  JMP NEWSCRN

;^END
SCRBOT:
  MOV DX,CURLOC
  MOV AL,24		;BOTTOM ROW
  SUB AL,DH		;CURSOR ROW
  MOV AH,80
  MUL AH
  ADD CURPTR,AX
;NOW TEST FOR END OF FILE
  MOV AX,TOPLEF 	;SEGMENT & TOPLEFT OF SCREEN
  CMP AX,LTOPLEF
  JNC SCRBOT2		;IF AT OR PAST LAST TOPLEFT
  MOV DH,24		;BOTTOM ROW
  CALL MOVCUR
  JMP NEWSCRN
SCRBOT2:
  CALL CUREND
  JMP NEWSCRN

;^PGDN
GOEND:
  MOV AX,LTOPLEF
  CMP AX,TOPLEF
  JC SCRBOT		;IF FILE DOESN't fill screen
  MOV TOPLEF,AX
  MOV AX,LASTCOL
  MOV DX,AX
  MOV DH,018H		;ROW 24
  ADD AX,1840		;80*23
  MOV CURPTR,AX
  CALL MOVCUR
  JMP NEWSCRN

;HOME
LFTSIDE:
  MOV DX,CURLOC
  PUSH DX
  SUB DH,DH
  SUB CURPTR,DX 	;DECREMENT CURPTR TO 1ST COL
  POP DX
  SUB DL,DL
  CALL MOVCUR
  JMP NEWSCRN

;END
RTSIDE:
  MOV AX,TOPLEF
  CMP AX,LTOPLEF
  JC RTSIDE2
  MOV CL,4
  SHL AX,CL
  ADD AX,CURPTR
  MOV BX,FILENDO
  SUB BX,LASTCOL
  CMP AX,BX		;BEGINNING OF LAST LINE OF FILE
  JC RTSIDE2
  CALL CUREND
  JMP NEWSCRN

RTSIDE2:
  MOV DX,CURLOC
  MOV AL,79
  SUB AL,DL
  SUB AH,AH
  ADD CURPTR,AX
  MOV DL,79
  CALL MOVCUR
  JMP NEWSCRN

;PGUP
PREV:
  MOV AX,FTOPLEF
  CMP AX,TOPLEF
  IF Z JMP WATE
  ADD AX,078		;1920D SHIFTED RIGHT (24*80) SCREEN
  CMP AX,TOPLEF
  IF NC JMP FILETOP
  SUB TOPLEF,078
  JMP NEWSCRN

;PGDN
NEXT:
  MOV AX,TOPLEF
  CMP AX,LTOPLEF
  IF NC JMP WATE	;IF AT END OF FILE
  ADD AX,078		;1920D SHIFTED RIGHT
  MOV TOPLEF,AX
  CMP AX,LTOPLEF
  IF NC CALL CUREND
  JMP NEWSCRN

;LEFT ARROW
CURLFT:
  CALL LFTCUR
  JMP NEWSCRN
  
;RIGHT ARROW
CURRT:
  CALL RTCUR
  JMP NEWSCRN

;^RIGHT ARROW
MOVRT:
  MOV CX,10
RTLP:
  PUSH CX
  CALL RTCUR
  POP CX
  LOOP RTLP
  JMP NEWSCRN

;^LEFT ARROW
MOVLFT:
  MOV CX,10
LFTLP:
  PUSH CX
  CALL LFTCUR
  POP CX
  LOOP LFTLP
  JMP NEWSCRN

;UP ARROW
CURUP:
  CALL SCRLOCK
  JNZ UP		;IF SCROLLLOCK IS ON
  MOV DX,CURLOC
  CMP DH,1
  JE CURUP2		;IF ON TOP LINE
  DEC DH
  CALL MOVCUR
  SUB CURPTR,80
  JMP NEWSCRN

CURUP2:
  MOV AX,TOPLEF
  CMP AX,FTOPLEF
  IF Z JMP WATE
  SUB TOPLEF,5
  JMP NEWSCRN

;SCROLLLOCK ON
UP:
  MOV AX,TOPLEF
  CMP AX,FTOPLEF
  IF Z JMP WATE 	;IF AT BEGINNING OF FILE
  SUB TOPLEF,5
  MOV DX,CURLOC
  CMP DH,24
  JE DOWNEND		;IF AT BOTTOM
  INC DH
  CALL MOVCUR
  ADD CURPTR,80 	;BECAUSE OF TOPLEF CHANGE
  JMP NEWSCRN

JMPWATE:
  JMP WATE

;DOWN ARROW
CURDN:
  CALL SCRLOCK
  JNZ DOWN		;IF SCROLLLOCK IS ON
  MOV AX,TOPLEF
  CMP AX,LTOPLEF
  JC CURDN3		;IF NOT AT LAST SCREEN OF FILE
  MOV CL,4
  SHL AX,CL
  ADD AX,CURPTR
  MOV BX,FILENDO
  NEG AX
  ADD BX,AX
  CMP BX,80
  JC JMPWATE
CURDN3: 
  MOV DX,CURLOC
  CMP DH,24
  JE CURDN2		;IF ON BOTTOM LINE
  INC DH
  CALL MOVCUR
  ADD CURPTR,80
  JMP NEWSCRN
  
CURDN2:
  MOV AX,TOPLEF
  ADD AX,5
  MOV TOPLEF,AX
  CMP AX,LTOPLEF
  IF NC CALL CUREND	;IF AT LAST SCREEN OF FILE
  JMP NEWSCRN		;DON't need to increment curptr
  
;SCROLLLOCK ON
DOWN:
  MOV AX,TOPLEF
  CMP AX,LTOPLEF
  JNC JMPWATE		;IF AT END OF FILE
  ADD TOPLEF,5		;80 SHIFTED RIGHT
  MOV DX,CURLOC
  CMP DH,1
  JE DOWNEND		;IF CURSOR IS ON TOP LINE
  DEC DH
  CALL MOVCUR
  SUB CURPTR,80 	;BECAUSE OF TOPLEF CHANGE
DOWNEND:
  JMP NEWSCRN

;***

;JUMP TO INPUT HEX ADDRESS
JUMP:
  MOV SI,OFFSET JUMP?
  CALL TOP
  MOV BP,96		;FOR SCREEN LOCATION IN GETSTR
  CALL GETSTR		;GET INPUT
  IF S JMP FINDXIT	;IF NO INPUT
  MOV SI,DI		;JUST AFTER LAST INPUT CHAR ON SCREEN
  SUB DI,DI		;FOR OFFSET ADDRESS
  SUB BX,BX		;FOR SEGMENT ADDRESS
  MOV DX,0004		;DH FOR CL & DL FOR LOOP
;GET OFFSET ADDRESS
L1:
  SUB SI,2
  CMP SI,96		;INPUT SCREEN LOCATION
  JL  >L2		;IF NO GOOD INPUT
  MOV AL,ES:[SI]
  CALL HEX2BIN		;CONVERT TO BINARY
  JC  L1		;IF NOT HEXADECIMAL
  MOV CL,DH
  ADD DH,4		;TO ROL AX TO NEXT NIBBLE TO LEFT
  SUB AH,AH		;ROL CHANGES IT
  ROL AX,CL
  OR  DI,AX		;TA DAA!
  DEC DL
  JNZ L1
;GET SEGMENT ADDRESS (IF FIFTH CHAR NOT INPUT,IT's 0)
  SUB SI,2
  MOV AL,ES:[SI]
  CALL HEX2BIN
  JC >L2
  MOV BL,AL
  JMP SHORT >L21
L2:
  CMP DI,BEGIN
  IF C MOV DI,BEGIN
L21:
  SUB DI,BEGIN
  SBB BX,0
  CMP BX,FILSIZS
  JC >L4
  JG >L3
  CMP DI,FILSIZO
  JC >L4
L3:
  MOV DI,FILSIZO
  MOV BX,FILSIZS
L4:
ITSEXE:
  MOV SAVES,ES
  MOV BP,FTOPLEF
  MOV AX,DI
  MOV DX,BX
  MOV CL,4
  ROR BX,CL
  JMP THERE

FIND:	
  MOV SI,OFFSET FIND?
  CALL TOP
  MOV BP,90		;SCREEN ADDRESS OFFSET
  CALL GETSTR		;GET INPUT & STRING COUNT-1 IN STRCNT
  IF S JMP FINDXIT	;IF NO INPUT OR ESC PRESSED
  MOV SI,90
  MOV DI,OFFSET FINDSTR
;CHECK TO SEE IF ASCII STRING
  CMP B ES:[SI],027	;'
  JZ FINDASCII
  CMP B ES:[SI],022	;"
  JZ FINDASCII

;CONVERT ASCII HEX TO BINARY & STORE IT IN FINDSTR
  MOV STRCNT,0		;RE-COMPUTE IT
  MOV CX,18
CONVHEX:
  MOV AL,ES:[SI]
  CMP AL,' '
  JZ SKIP
  CMP AL,','
  JZ SKIP
  CALL HEX2BIN		;CONVERTS ASCII HEX CHAR TO BINARY
  IF C JMP FINDXIT	;IF NOT ASCII HEX INPUT
  PUSH CX
  MOV CL,4
  SHL AL,CL
  POP CX
  MOV DS:[DI],AL
  ADD SI,2		;TO NEXT ASCII HEX INPUT
  MOV AL,ES:[SI]
  CALL HEX2BIN
  JNC PART2
  CMP AL,' '
  JZ >L1
  CMP AL,','
  JZ >L1
  JMP FINDXIT
L1:
  PUSH CX
  MOV CL,4
  MOV AL,DS:[DI]
  SHR AL,CL		;PUT FIRST DIGIT BACK AT RIGHT SIDE
  POP CX
  MOV DS:[DI],AL
  JMP SHORT PART1
PART2:
  OR DS:[DI],AL
PART1:
  INC DI
  INC STRCNT
SKIP:
  ADD SI,2
  LOOP CONVHEX
  DEC STRCNT
  JMP SHORT REPEAT

FINDASCII:
  ADD SI,2		;DON't look for the ' or "
  DEC STRCNT
  MOV CX,17
;STORE STRING IN FINDSTR
STORSTR:
  MOV AL,ES:[SI]
  CMP AL,ES:[90]	;' or "
  JNZ >L4
  DEC STRCNT
  MOV AL,' '
L4:
  MOV DS:[DI],AL
  INC DI
  ADD SI,2
  LOOP STORSTR

REPEAT:
  MOV BP,TOPLEF
  MOV SI,OFFSET SEARCH	;'SEARCHING...'
  CALL TOP
;SEARCH FOR STRING
  MOV DI,BP		;EITHER TOPLEF OR FTOPLEF
  MOV BX,DI		;FOR ABSOLUTE SEGMENT ADDR
  AND BX,0F000
  MOV CL,4
  SHL DI,CL
  MOV AX,CURPTR
  INC AX		;TO START LOOKING 1 BYTE BEYOND CURRENT CURSOR LOCATION
  ADD DI,AX		;TO GET ABSOLUTE OFFSET ADDR
  IF C ADD BX,01000
  MOV BP,BX		;FOR CURRENT ABSOLUTE SEG ADDR
  MOV SAVES,ES
  MOV ES,BP		;BEGINNING OF FILE SEGMENT
  ROL BX,CL		;MOVE LEFT NIBBLE TO RIGHT (CL IS ALREADY 4)
  MOV CX,FILENDO	;FOR REPNZ SCASB,BELOW (MAY BE 0,SEE BELOW)
  INC CX		;BECAUSE CURPTR WAS INCREMENTED
  NEG BX
  ADD BX,FILENDS	;TO GET FILENDS - CURRENT SEGMENT IN BX
FINDLOOP: 
  IF NZ MOV CX,0FFFF	;IF CURSOR NOT IN SAME ABSOLUTE SEGEMENT AS FILEND
  SUB CX,DI		;TO GET EITHER FILENDO OR 0FFFF - CURRENT ABSOLUTE OFFSET
FINDLP2:
  OR CX,CX
  JZ QUITFIND
  MOV SI,OFFSET FINDSTR ;ADDRESS OF STRING TO FIND
  MOV AL,[SI]		;FIRST CHAR
  REPNZ SCASB		;REPEAT UNTIL Z=TRUE OR CX=0
  JZ STRCHK		;IF FIRST CHAR FOUND
  OR BX,BX		;NO. OF REMAINING SEGMENTS TO SEARCH
  JNZ NEWSEG
QUITFIND:
  JMP NOTFOUND
NEWSEG:
  SCASB 		;BECAUSE DI ONLY GOT TO 0FFFF, NOT 0
  JZ STRCHK
  ADD BP,01000
  MOV ES,BP		;INCREMENTS ABSOLUTE SEGMENT
  MOV CX,FILENDO
  INC CX
  DEC BX
  JMP SHORT FINDLOOP

;CALLED ONLY IN EXTREMELY RARE CIRCUMSTANCE, BUT I GUESS IT's necessary...
CHNGSEG:
  OR BX,BX
  JZ NOTFOUND
  PUSH BP,ES
  ADD BP,01000
  MOV ES,BP
  REPZ CMPSB
  POP ES,BP
  JMP SHORT RETCHKLP

STRCHK:
  MOV AX,DI		;SAVE IT
  MOV DX,CX		;DITTO
  MOV CX,STRCNT 	;STRING LENGTH-1 FROM GETSTR SUBROUTINE
  OR CX,CX
  JZ FOUND		;IF ONLY SEARCHING FOR 1 CHAR
  INC SI		;POINT TO REMAINDER OF STRING
CHKLP:
  OR DI,DI
  JZ CHNGSEG		;IF SEARCHING PAST END OF SEGMENT
  CMPSB 		;COMPARE STRINGS (REPEAT UNTIL Z=FALSE OR CX=0)
  LOOPZ CHKLP
RETCHKLP:
  MOV CX,DX
  MOV DI,AX
  JNZ FINDLP2		;IF STRING NOT FOUND

;JUMP TO ADDRESS
FOUND:
  MOV DX,BP		;CURRENT SEGMENT
  MOV CL,4
  ROL DX,CL
  OR DI,DI
  JNZ SAMESEG
  DEC DX
  SUB BP,01000
SAMESEG:
  DEC DI		;OFFSET ADDR
  MOV AX,DI
  SUB AX,BUFOFF
  SBB DX,BUFSEG
  SUB AX,HEADSIZ
  SBB DX,0
  MOV BX,BP		;SEG ADDR
  SUB BP,BP		;USED LATER (JUMP ALSO USES BP LATER)

THERE:
  CMP DX,010		;SEGMENT ADDRESS
  JNC NOTFOUND		;AN IMPOSSIBILITY...
  MOV CX,80
  DIV CX		;REMAINDER IS IN DX (& DL = COLUMN)
  MOV CURPTR,DX 	;COLUMN (DH=0)
  SUB DI,DX		;TO GET TOPLEF
  IF C SUB BX,01000
  MOV CL,4
  SHR DI,CL
  ADD DI,BX
  ADD DI,BP
  MOV TOPLEF,DI 	;TA-DAA!
  MOV DH,1		;PUT CURSOR ON FIRST ROW
  MOV CURLOC,DX 	;FOR MOVCUR
;CLEAR MESSAGE & EXIT
NOTFOUND:
  MOV ES,SAVES
FINDXIT: 
  CALL WRITEBLANKS
  MOV DX,CURLOC
  CALL MOVCUR
  MOV AH,1		;FUNCTION TO CHANGE CURSOR SHAPE
  MOV CX,7		;TOP & BOTTOM ROW OF CURSOR
  INT 010
  JMP NEWSCRN

;LOOK FOR STRING AGAIN
AGAIN:	
  CALL HIDECUR
  JMP SHORT REPEAT

NOTHERE:
  MOV SI,081
  MOV AL,[080]
  SUB AH,AH
  ADD SI,AX
  MOV B[SI],'$'
  MOV DX,081
  MOV AH,9
  INT 021
  MOV DX,OFFSET NOFILE
  MOV AH,9
  INT 021
  MOV AX,04C00
  INT 021

WRITE:
  MOV AX,04200		;FUNCTION TO MOVE FILE POINTER TO BEGINNING OF FILE
  MOV BX,HANDLE
  SUB CX,CX
  SUB DX,DX
  INT 021
;WRITE FILE TO DISK
  MOV BP,FILSIZS
  MOV DX,FILEBEG
  MOV AX,FILSIZO
WRITELP:
  MOV TEMPFIL,AX
  MOV CX,0FFF0
  OR BP,BP
  IF Z MOV CX,AX
  MOV DS,DX
  PUSH DX
  SUB DX,DX
  MOV AH,040		;FUNCTION TO WRITE FILE
  INT 021
  MOV DX,CS
  MOV DS,DX
  POP DX
  ADD DX,0FFF
  JC EXIT
  OR AX,AX
  JZ EXIT
  MOV AX,TEMPFIL
  SUB AX,0FFF0
  SBB BP,0
  JNS WRITELP

;RETURN TO DOS
EXIT:	
;RESTORE OLD CURSOR LOCATION
  MOV DX,OLDCUR	;OLD CURSOR LOCATION
  MOV AH,1		;FUNCTION TO SET CURSOR TYPE
  MOV CX,CURSHPE	;STARTING & ENDING LINE OF CURSOR
  INT 010
  CALL MOVCUR
;BLANK BORDER
  MOV AH,0B
  SUB BX,BX
  INT 010
;RESTORE OLD SCREEN
  SUB DI,DI
  MOV SI,OLDSCR
  MOV CX,2000
  REP MOVSW

  MOV AX,04C00		;TERMINATE WITH RETURN CODE
  INT 021		;RETURN TO DOS

;******SUBROUTINES******

DISPLTOP:
  MOV SI,OFFSET TOPLINE
  SUB DI,DI		;LOCATION ON SCREEN
  MOV CX,41		;FOR COUNT
  MOV AH,TOPATTRIB
  CMP MODE,7		;MONOCHROME
  IF Z MOV AH,070	;REVERSE IMAGE
  CALL MOVIT		;MOVE [SI] INTO [DI] & INC DI CX TIMES
  MOV AL,' '
  MOV CX,24
  REP STOSW
  MOV SI,OFFSET HELP?
  MOV CX,15
  CALL MOVIT
  RET

;PUT 'FIND:' or 'JUMP TO:' on top line of screen
TOP:
  MOV CX,13
  MOV DI,78
  MOV AH,TOPATTRIB
  CMP MODE,7
  IF Z MOV AH,070
  CALL MOVIT
  MOV AL,' '
  MOV CX,12
  REP STOSW
  RET

WRITEBLANKS:
  MOV AL,' '
  MOV CX,25
  MOV DI,78
BLANKLP:
  STOSB
  INC DI
  LOOP BLANKLP
  RET

;TO MOVE A STRING AT [DI] TO [SI] (ATTRIBUTE IN AH)
MOVIT:	
  LODSB
  STOSW
  LOOP MOVIT
  RET

MOVIT2:
  LODSB
  CMP AL,07F
  JNC SHODOT
  CMP AL,020
  JNC SHOLET
SHODOT:
  MOV AL,'.'
SHOLET:
  STOSW
  LOOP MOVIT2
  RET

;TO PUT CURSOR AT END OF FILE
CUREND: 
  MOV DX,TOPLEF
  MOV CL,4
  SHL DX,CL
  MOV AX,FILENDO
  NEG DX
  ADD AX,DX
  MOV CURPTR,AX
  MOV CL,80
  DIV CL
  INC AL
  MOV DH,AL		;QUOTIENT (ANSWER) (FOR ROW)
  MOV DL,AH		;REMAINDER (FOR COLUMN)
  JMP SHORT MOVCUR

;PUT ROW IN DH & COL IN DL
GETCUR: 
  MOV AH,3
  SUB BH,BH
  INT 010
  MOV CURLOC,DX
  RET

;SAVE CURSOR LOCATION
HIDECUR:
  MOV DX,01900		;ROW 25,COL 0
  JMP SHORT MOVCUR2
  
;MOVE CURSOR TO ROW IN DH & COL IN DL
MOVCUR: 
  MOV CURLOC,DX
MOVCUR2:
  MOV AH,2
  SUB BH,BH
  INT 010
  RET

;TO JUMP TO A SUBROUTINE (SEMI-TRICK)
CASE:	
  POP BX		;RET ADDRESS
  MOV CL,[BX]		;NUMBER OF COMPARISONS TO MAKE
  SUB CH,CH
CASLOP: 
  INC BX		;TO A DB
  CMP AL,[BX]
  JE GO
  ADD BX,2		;TO A DW
  LOOP CASLOP
GO:
  INC BX		;TO A DW
  JMP [BX]

LCA:
;TO CHANGE BINARY TO HEX
BIN2HEXW:
  CALL SHOWORD
  MOV DS,TOPLEF
  LODSW
BIN2HEXW2:
  MOV CH,4
  MOV BX,AX
  JMP SHORT BIN2HEXSKP
LCD:
BIN2HEXB:
  CALL SHOBYTE
  MOV DS,TOPLEF
  LODSB
  MOV CH,2
  MOV BH,AL
BIN2HEXSKP:
  PUSH CS
  POP DS
BIN2HEX:
  MOV CL,4
BIN2HEXLP:
  ROL BX,CL		;MOVE LEFT BYTE TO RIGHT SIDE
  MOV AL,BL		;THIS IS NECESSARY
  AND AL,0F		;CLEAR LEFT BYTE
  ADD AL,'0'
  CMP AL,'9'
  IF A ADD AL,7
  STOSB
  INC DI
  DEC CH
  JNZ BIN2HEXLP
  RET

;CONVERT AL FROM HEX TO BINARY
HEX2BIN:
  CMP AL,'0'
  JB BADHEX
  CMP AL,':'
  JB HEX2		;IF NUMBER
  AND AL,0DFH		;MAKE LETTERS UPPERCASE
  CMP AL,'A'
  JB BADHEX
  CMP AL,'F'
  JA BADHEX
  SUB AL,7
HEX2:
  SUB AL,'0'
  CLC 
  RET
BADHEX: 
  STC
  RET

;MOVE CURSOR LEFT
LFTCUR: 
  MOV DX,CURLOC
  CMP DX,0100
  JE LFTTOP		;IF AT TOP LEFT OF SCREEN
  DEC CURPTR
  OR DL,DL
  JE PREVLIN
  DEC DL
  JMP SHORT LFTMOV
PREVLIN:
  DEC DH
  MOV DL,79
LFTMOV: 
  CALL MOVCUR
  CLC
LFTXIT: 
  RET

LFTTOP: 
  MOV AX,TOPLEF
  CMP AX,FTOPLEF
  JE LFTXIT		;IF AT BEGINNING OF FILE
  MOV DL,79
  CALL MOVCUR
  SUB TOPLEF,5		;80D SHIFTED RIGHT
  ADD CURPTR,79 	;BECAUSE OF TOPLEF CHANGE
  STC
  RET

;MOVE CURSOR RIGHT
RTCUR:	
  MOV AX,TOPLEF
  CMP AX,LTOPLEF
  JC RTCUR2		;IF NOT AT LAST SCREEN
  MOV BX,AX
  MOV CL,4
  ROL BX,CL
  AND BX,0F
  SHL AX,CL
  ADD AX,CURPTR
  IF C INC BX
  CMP BX,FILENDS
  JC RTCUR2		;IF CURRENT SEGMENT LESS THAN FILEND SEGMENT
  CMP AX,FILENDO
  JNC RTEXIT		;IF CURSOR WOULD GO BEYOND FILE END
RTCUR2: 
  INC CURPTR
  MOV DX,CURLOC
  CMP DL,79
  JE NEXLIN
  INC DL
  JMP SHORT RTMOV
NEXLIN: 
  CMP DH,24
  JE RTBOT
  INC DH
  SUB DL,DL
RTMOV:	
  CALL MOVCUR
RTEXIT: 
  CLC
  RET
  
RTBOT:	
  CMP AX,LTOPLEF
  JNC RTEXIT
  SUB DL,DL
  CALL MOVCUR
  ADD TOPLEF,5
  SUB CURPTR,80 	;BECAUSE OF TOPLEF CHANGE
  STC
  RET

;CHECK SCROLLLOCK ON OR OFF
SCRLOCK:
  PUSH ES
  SUB AX,AX
  MOV ES,AX
  TEST B ES:[0417],010
  POP ES
  RET

;GET STRING TO SEARCH FOR
GETSTR: 
  MOV DX,BP
  SHR DX,1
  CALL MOVCUR2
  MOV AH,1		;FUNCTION TO CHANGE CURSOR SHAPE
  MOV CX,0406		;TOP & BOTTOM ROW OF CURSOR
  INT 010
  SUB DX,DX		;FOR COUNT IN CMPSB, BELOW
  MOV DI,BP
CHKSTR: 
  SUB AH,AH		;READ KEYBOARD FUNCTION
  INT 016
  CMP AH,14		;BACKSPACE KEY
  JE ERASTR
  CMP AX,04B00		;LEFT ARROW KEY
  JE ERASTR
  CMP AL,8		;^H
  JE ERASTR
  CMP AL,0D		;ENTER KEY
  JE XITSTR
  CMP AL,01B		;ESC
  JNZ NOTESC
  SUB DX,DX		;AS A FLAG (TO SET SIGN FLAG)
  JMP SHORT XITSTR
;ERASE CHAR
ERASTR: 
  CMP DI,BP
  JE CHKSTR		;DON'T ERASE IF AT BEGINNING OF INPUT LOCATION
  DEC DI
  DEC DI
  PUSH DX
  MOV DX,DI
  SHR DX,1
  CALL MOVCUR2
  POP DX
  DEC DX
  MOV AH,TOPATTRIB
  MOV AL,' '
  ES MOV W[DI],AX
  CMP MODE,7
  IF Z ES MOV B[DI+1],070
  JMP SHORT CHKSTR
NOTESC:
  CMP AL,' '
  JC CHKSTR		;DON'T ACCEPT ANY OTHER ^CHARS
;PUT CHAR ON SCREEN
SHOSTR: 
  CMP DI,126		;LAST INPUT SPACE
  JE XITSTR		;EXIT
  STOSB
  INC DI
  PUSH DX
  MOV DX,DI
  SHR DX,1
  CALL MOVCUR2
  POP DX
  INC DX
  JMP SHORT CHKSTR
XITSTR: 
  DEC DX
  MOV STRCNT,DX
  RET

MENWRT: 
  MOV AH,SCRNATTRIB
  CMP MODE,7
  IF Z MOV AH,7
  SUB DI,DI
  MOV AL,' '
  MOV CX,2
  REP STOSW
  MOV DX,25		;ROWS
MENLP0: 
  MOV CX,80		;COLUMNS
MENLP:	
  LODSB
  OR AL,AL
  JE MENSK
  STOSW
  LOOP MENLP
MENSK:	
  REP STOSW
  OR SI,SI
  IF Z ADD DI,160
  DEC DX
  JNZ MENLP0
  MOV AL,179		;│
  MOV DI,160
  MOV CX,23
SIDELINES:
  STOSB
  ADD DI,157
  STOSB
  INC DI
  LOOP SIDELINES
  MOV B ES:[0],218	;┌
  MOV B ES:[3840],192	;└
  MOV B ES:[158],191	;┐
  MOV B ES:[3998],217	;┘
  SUB AH,AH
  INT 016H		;READ KEYBOARD
RTN:
  RET

;********DISASSEMBLE SUBROUTINES

L00:
  CALL GETBYTE2
  MOV BX,OFFSET REGB
  MOV B[BW],'B'
  CALL MODRMBITS
  MOV AL,','
  STOSB
  INC DI
  MOV BX,OFFSET REGB
  JMP NBITS

L01:
  CALL GETBYTE2
  MOV BX,OFFSET REGW
  MOV B[BW],'W'
  CALL MODRMBITS
  MOV AL,','
  STOSB
  INC DI
  MOV BX,OFFSET REGW
  JMP NBITS

L02:
  CALL GETBYTE2
  MOV BX,OFFSET REGB
  CALL NBITS
  MOV AL,','
  STOSB
  INC DI
  MOV BX,OFFSET REGB
  MOV B[BW],'B'
  JMP MODRMBITS

L03:
  CALL GETBYTE2
  MOV BX,OFFSET REGW
  CALL NBITS
  MOV AL,','
  STOSB
  INC DI
  MOV BX,OFFSET REGW
  MOV B[BW],'W'
  JMP MODRMBITS

L04:
  MOV AX,'LA'
  CALL L045
  JMP BIN2HEXB

L05:
  MOV AX,'XA'
  CALL L045
  JMP BIN2HEXW

L045:
  STOSB
  INC DI
  XCHG AL,AH
  STOSB
  INC DI
  MOV AL,','
  STOSB
  INC DI
  RET

L06:
  MOV AX,'SE'
  JMP SHORT AXTODI

L0E:
  MOV AX,'SC'
  JMP SHORT AXTODI

L16:
  MOV AX,'SS'
  JMP SHORT AXTODI

L1E:
  MOV AX,'SD'
  JMP SHORT AXTODI

L40:
  MOV AX,'XA'
  JMP SHORT AXTODI
L41:
  MOV AX,'XC'
  JMP SHORT AXTODI
L42:
  MOV AX,'XD'
  JMP SHORT AXTODI
L43:
  MOV AX,'XB'
  JMP SHORT AXTODI
L44:
  MOV AX,'PS'
  JMP SHORT AXTODI
L45:
  MOV AX,'PB'
  JMP SHORT AXTODI
L46:
  MOV AX,'IS'
  JMP SHORT AXTODI
L47:
  MOV AX,'ID'
AXTODI:
  STOSB
  INC DI
  XCHG AL,AH
  STOSB
  INC DI
  RET

L70:
  MOV DS,TOPLEF
  LODSB
  CBW
  MOV DX,2
  CALL RELATIVE
  JMP SHOBYTE

L80:
  SUB BP,BP		;TO INDEX TO IMMED,SHIFT,GRP1,OR GRP2
  MOV BX,OFFSET REGB
  MOV SAVEBX,BX
  MOV B[BW],'B'
  CALL EIGHTX
  MOV AL,','
  STOSB
  INC DI
  JMP BIN2HEXB

L81:
  SUB BP,BP
  MOV BX,OFFSET REGW
  MOV SAVEBX,BX
  MOV B[BW],'W'
  CALL EIGHTX
  MOV AL,','
  STOSB
  INC DI
  JMP BIN2HEXW

L83:
  SUB BP,BP
  MOV BX,OFFSET REGW
  MOV SAVEBX,BX
  MOV B[BW],'W'
  CALL EIGHTX
  MOV AL,','
  STOSB
  INC DI
  MOV AL,'0'
  TEST B[SI],080
  IF NZ MOV AL,'F'
  STOSB
  INC DI
  STOSB
  INC DI
  JMP BIN2HEXB

EIGHTX:
  CALL GETBYTE2
  SUB DI,2		;WRITE OVER BLANK
  MOV CL,3
  SHR AX,CL		;LOOK AT R BITS
  AND AX,7		;CLEAR ALL BUT LOW 3 BITS
  SHL AX,1		;DOUBLE IT
  MOV BX,OFFSET ISGGPTRS
  ADD BX,BP
  MOV BX,[BX]
  ADD BX,AX
  PUSH SI
  MOV SI,[BX]		;POINT TO STRING
ISGGLP:
  LODSB
  STOSB
  INC DI
  CMP AL,' '
  JNZ ISGGLP
  POP SI
  MOV BX,SAVEBX
  JMP MODRMBITS

L8C:
  MOV BX,OFFSET REGW
  MOV B[BW],'W'
  CALL GETBYTE2
  CALL MODRMBITS
  MOV AL,','
  STOSB
  INC DI
  PUSH SI
  MOV SI,OFFSET SEGS
  MOV CL,3
  MOV AL,BYTE2
  SHR AX,CL
  AND AX,7
  SHL AX,1
  ADD SI,AX
  MOVSB
  INC DI
  MOVSB
  INC DI
  POP SI
  RET

L8E:
  CALL GETBYTE2
  PUSH SI
  MOV SI,OFFSET SEGS
  MOV CL,3
  SHR AX,CL
  AND AX,7
  SHL AX,1
  ADD SI,AX
  MOVSB
  INC DI
  MOVSB
  INC DI
  POP SI
  MOV AL,','
  STOSB
  INC DI
L8F:
  MOV BX,OFFSET REGW
  MOV B[BW],'W'
  JMP MODRMBITS

L91:
  CALL L41
  JMP SHORT L9X
L92:
  CALL L42
  JMP SHORT L9X
L93:
  CALL L43
  JMP SHORT L9X
L94:
  CALL L44
  JMP SHORT L9X
L95:
  CALL L45
  JMP SHORT L9X
L96:
  CALL L46
  JMP SHORT L9X
L97:
  CALL L47
L9X:
  MOV AL,','
  STOSB
  INC DI
  MOV AX,'XA'
  STOSB
  INC DI
  XCHG AL,AH
  STOSB
  INC DI
  RET

L9A:
  ADD SI,2
  CALL BIN2HEXW
  MOV AL,':'
  STOSB
  INC DI
  SUB SI,4
  CALL BIN2HEXW
  ADD SI,2
  RET

LA0:
  MOV AX,'LA'
  MOV B[BW],'B'
  JMP SHORT LA01
LA1:
  MOV AX,'XA'
  MOV B[BW],'W'
LA01:
  STOSB
  INC DI
  XCHG AH,AL
  STOSB
  INC DI
  MOV AL,','
  STOSB
  INC DI
  MOV AL,B[BW]
  STOSB
  INC DI
  MOV AL,'['
  STOSB
  INC DI
  CALL BIN2HEXW
  MOV AL,']'
  STOSB
  RET

LA2:
  MOV B[BW],'B'
  CALL LA23
  MOV AX,'LA'
  JMP SHORT LAX
LA3:
  MOV B[BW],'W'
  CALL LA23
  MOV AX,'XA'
LAX:
  STOSB
  INC DI
  XCHG AL,AH
  STOSB
  RET

LA23:
  MOV AL,B[BW]
  STOSB
  INC DI
  MOV AL,'['
  STOSB
  INC DI
  CALL BIN2HEXW
  MOV AL,']'
  STOSB
  INC DI
  MOV AL,','
  STOSB
  INC DI
  RET

LA4:
  SUB DI,2
  ES MOV B[DI],'B'
  RET

LA5:
  SUB DI,2
  ES MOV B[DI],'W'
  RET

LB0:
  MOV AX,'LA'
  JMP SHORT LBX
LB1:
  MOV AX,'LC'
  JMP SHORT LBX
LB2:
  MOV AX,'LD'
  JMP SHORT LBX
LB3:
  MOV AX,'LB'
  JMP SHORT LBX
LB4:
  MOV AX,'HA'
  JMP SHORT LBX
LB5:
  MOV AX,'HC'
  JMP SHORT LBX
LB6:
  MOV AX,'HD'
  JMP SHORT LBX
LB7:
  MOV AX,'HB'
  JMP SHORT LBX
LB8:
  MOV AX,'XA'
  JMP SHORT LBX2
LB9:
  MOV AX,'XC'
  JMP SHORT LBX2
LBA:
  MOV AX,'XD'
  JMP SHORT LBX2
LBB:
  MOV AX,'XB'
  JMP SHORT LBX2
LBC:
  MOV AX,'PS'
  JMP SHORT LBX2
LBD:
  MOV AX,'PB'
  JMP SHORT LBX2
LBE:
  MOV AX,'IS'
  JMP SHORT LBX2
LBF:
  MOV AX,'ID'
  JMP SHORT LBX2
LBX:
  STOSB
  INC DI
  XCHG AL,AH
  STOSB
  INC DI
  MOV AL,','
  STOSB
  INC DI
  JMP BIN2HEXB

LBX2:
  STOSB
  INC DI
  XCHG AL,AH
  STOSB
  INC DI
  MOV AL,','
  STOSB
  INC DI
  JMP BIN2HEXW

LC4:
  CALL GETBYTE2
  MOV BX,OFFSET REGW
  CALL NBITS
  MOV AL,','
  STOSB
  INC DI
  MOV BX,OFFSET REGW
  MOV B[BW],'W'
  JMP MODRMBITS

LC6:
  MOV BX,OFFSET REGB
  MOV B[BW],'B'
  CALL LC67
  JMP BIN2HEXB

LC7:
  MOV BX,OFFSET REGW
  MOV B[BW],'W'
  CALL LC67
  JMP BIN2HEXW

LC67:
  CALL GETBYTE2
  CALL MODRMBITS
  MOV AL,','
  STOSB
  INC DI
  RET

LD0:
  MOV BX,OFFSET REGB
  MOV B[BW],'B'
  JMP SHORT LDX
LD1:
  MOV BX,OFFSET REGW
  MOV B[BW],'W'
LDX:
  MOV SAVEBX,BX
  MOV BP,2		;TO INDEX TO IMMED
  CALL EIGHTX
  MOV AL,','
  STOSB
  INC DI
  MOV AL,'1'
  STOSB
  RET

LD2:
  MOV BX,OFFSET REGB
  MOV B[BW],'B'
  JMP SHORT LDX2
LD3:
  MOV BX,OFFSET REGW
  MOV B[BW],'W'
LDX2:
  MOV SAVEBX,BX
  MOV BP,2		;TO INDEX TO SHIFT
  CALL EIGHTX
  MOV AL,','
  STOSB
  INC DI
  MOV AX,'LC'
  STOSB
  INC DI
  XCHG AL,AH
  STOSB
  RET

LE4:
  MOV AX,'LA'
  JMP SHORT LE45
LE5:
  MOV AX,'XA'
LE45:
  STOSB
  INC DI
  XCHG AL,AH
  STOSB
  INC DI
  MOV AL,','
  STOSB
  INC DI
  JMP BIN2HEXB

LE6:
  CALL BIN2HEXB
  MOV AL,','
  STOSB
  INC DI
  MOV AX,'LA'
  JMP SHORT LE67
LE7:
  CALL BIN2HEXB
  MOV AL,','
  STOSB
  INC DI
  MOV AX,'XA'
LE67:
  STOSB
  INC DI
  XCHG AL,AH
  STOSB
  RET

LE8:
  MOV DS,TOPLEF
  LODSW
  MOV DX,3
  CALL RELATIVE
  JMP SHOWORD

LEB:
  MOV DS,TOPLEF
  LODSB
  CBW
  MOV DX,2
  CALL RELATIVE
  JMP SHOBYTE

LEC:
  MOV AX,'LA'
  JMP SHORT LECD
LED:
  MOV AX,'XA'
LECD:
  STOSB
  INC DI
  XCHG AL,AH
  STOSB
  INC DI
  MOV AL,','
  STOSB
  INC DI
  MOV AX,'XD'
  JMP SHORT LEEF

LEE:
  MOV AX,'XD'
  STOSB
  INC DI
  XCHG AL,AH
  STOSB
  INC DI
  MOV AL,','
  STOSB
  INC DI
  MOV AX,'LA'
  JMP SHORT LEEF
LEF:
  MOV AX,'XD'
  STOSB
  INC DI
  XCHG AL,AH
  STOSB
  INC DI
  MOV AL,','
  STOSB
  INC DI
  MOV AX,'XA'
LEEF:
  STOSB
  INC DI
  XCHG AL,AH
  STOSB
  JMP SHOBYTE

LF3:
  MOV DS,TOPLEF
  MOV AL,[SI]
  MOV CX,CS
  MOV DS,CX
  AND AL,0A6
  CMP AL,0A6
  JNZ LF2		;IF NEXT BYTE ISN'T 0A6, 0A7, 0AE, OR 0AF
  SUB DI,2
  MOV AL,'E'
  STOSB
  ADD DI,3
LF2:
  CALL SHOBYTE
  JMP DIS2

LF6:
  MOV BX,OFFSET REGB
  MOV B[BW],'B'
  CALL LF67
  JMP BIN2HEXB

LF7:
  MOV BX,OFFSET REGW
  MOV B[BW],'W'
  CALL LF67
  JMP BIN2HEXW

LF67:
  CALL GETBYTE2
  SUB DI,2		;WRITE OVER BLANK
  MOV CL,3
  SHR AX,CL		;LOOK AT R BITS
  AND AX,7		;CLEAR ALL BUT LOW 3 BITS
  CMP AL,1
  JNZ >L1
L2:
  POP CX		;PREVIOUS RET ADDRESS
  RET			;NO INSTRUCTION FOR THIS
L1:
  MOV SAVES,AX
  MOV BP,4		;TO INDEX TO IMMED,SHIFT,GRP1,OR GRP2
  SHL AX,1		;DOUBLE IT
  CALL LFX
  CALL MODRMBITS
  MOV AX,SAVES
  OR AX,AX
  JNZ L2		;ONLY TEST INSTRUCTION NEEDS ANOTHER NUMBER
  MOV AL,','
  STOSB
  INC DI
  RET

LFE:
  MOV BP,6
  MOV BX,OFFSET REGB
  MOV B[BW],'B'
  CALL GETBYTE2
  SUB DI,2		;WRITE OVER BLANK
  MOV CL,3
  SHR AX,CL		;LOOK AT R BITS
  AND AX,7		;CLEAR ALL BUT LOW 3 BITS
  CMP AX,2
  IF NC RET		;ONLY 0FF INSTRUCTION CAN USE HIGHER
  SHL AX,1		;DOUBLE IT
  CALL LFX
  JMP MODRMBITS

LFF:
  MOV BP,6
  MOV BX,OFFSET REGW
  MOV B[BW],'W'
  CALL GETBYTE2
  SUB DI,2		;WRITE OVER BLANK
  MOV CL,3
  SHR AX,CL		;LOOK AT R BITS
  AND AX,7		;CLEAR ALL BUT LOW 3 BITS
  CMP AL,7
  IF Z RET		;NO INSTRUCTION FOR THIS
  CMP AL,3
  IF Z MOV B[BW],'D'
  CMP AL,5
  IF Z MOV B[BW],'D'
  SHL AX,1		;DOUBLE IT
  CALL LFX
  JMP MODRMBITS

LFX:
  MOV SAVEBX,BX
  MOV BX,OFFSET ISGGPTRS
  ADD BX,BP
  MOV BX,[BX]
  ADD BX,AX
  PUSH SI
  MOV SI,[BX]		;POINT TO STRING
ISGGLP2:
  LODSB
  STOSB
  INC DI
  CMP AL,' '
  JNZ ISGGLP2
  POP SI
  MOV BX,SAVEBX
  RET

RELATIVE:
  MOV CX,CS
  MOV DS,CX
  MOV BX,ABSLOC1	;HIGH NIBBLE OF CURRENT LOCATION
  ADD DX,ABSLOC2	;ADD NEXT INSTR ADDR TO LOW NIBBLES OF CURRENT LOCATION
  IF O ADD BX,01000
  TEST DX,08000
  JZ >L1		;IF HI BIT NOT SET
  TEST AX,08000
  JZ >L05		;IF HI BIT NOT SET
  ADD DX,AX
  JMP SHORT >L2
L05:
  ADD DX,AX
  IF O ADD BX,01000
  JMP SHORT >L2
L1:
  TEST AX,08000
  JZ >L15		;IF HI BIT NOT SET
  ADD DX,AX
  IF O SUB BX,01000
  JMP SHORT >L2
L15:
  ADD DX,AX
L2:
  MOV CH,1
  CALL BIN2HEX
  MOV BX,DX
  MOV CH,4
  JMP BIN2HEX

GETBYTE2:
  CALL SHOBYTE
  MOV DS,TOPLEF
  LODSB 		;2ND BYTE
  MOV CX,CS
  MOV DS,CX
  MOV BYTE2,AL
  RET

;GET N BIT INFO (2ND BYTE = 2MOD BITS, 3 N BITS, & 3 R/M BITS)
NBITS:
  MOV AL,BYTE2
  MOV CL,3
  SHR AX,CL		;LOOK AT 3 REG BITS
  AND AX,7
  SHL AX,1		;DOUBLE IT
  PUSH SI
  MOV SI,BX		;EITHER OFFSET REGB OR REGW OR [ISGGPTRS]
  ADD SI,AX
  MOVSB
  INC DI
  MOVSB
  INC DI
  POP SI
  RET

;GET MOD & R/M BIT INFO
MODRMBITS:
  MOV AL,BYTE2
  MOV DL,AL
  AND AX,7		;TO JUST LOOK AT R/M BITS
  MOV CL,6
  SHR DL,CL		;LOOK AT 2 MOD BITS
  CMP DL,3		;11B
  JNZ NOTREG		;MOD R/M IS NOT TREATED AS A REGISTER
  SHL AX,1		;DOUBLE IT
  PUSH SI
  MOV SI,BX		;POINTING TO EITHER REGB OR REGW
  ADD SI,AX
  MOVSB
  INC DI
  MOVSB
  INC DI
  POP SI
  RET

NOTREG:
  OR DL,DL		;MOD BITS
  JNZ USEADDR
  CMP AL,6		;110B
  JNZ USEADDR		;IF R/M BITS <> 110B
;SPECIAL CASE (HIGH ADDRESS, LOW ADDRESS)
  MOV AL,BW
  STOSB
  INC DI
  MOV AL,'['
  STOSB
  INC DI
ADDRESS:
  INC SI
  CALL BIN2HEXB
  SUB SI,2
  CALL BIN2HEXB
  INC SI
  MOV AL,']'
  STOSB
  INC DI
  RET

USEADDR:
  PUSH AX
  MOV AL,[BW]
  STOSB
  INC DI
  POP AX
  MOV CL,3
  SHL AX,CL		;MUL 8 (TO INDEX INTO ADDR)
  PUSH SI
  MOV SI,OFFSET ADDR
  ADD SI,AX
ADDRLP:
  MOVSB
  INC DI
  CMP B[SI],' '
  JNZ ADDRLP
  POP SI
  OR DL,DL		;MOD BITS
  IF Z RET		;IF NO EXTRA DISPLACEMENT
  SUB DI,2		;WRITE OVER ']'
  MOV AL,'+'
  STOSB
  INC DI
  CMP DL,1
  JNZ ADDRESS		;IF FOLLOWING BYTE IS NOT SIGN-EXTENDED TO WORD
  MOV DS,TOPLEF
  MOV CX,CS
  TEST B[SI],080
  JZ NOTNEG		;IF HIGH BIT NOT SET
  NEG B[SI]
  ES MOV B[DI-2],'-'
NOTNEG:
  MOV DS,CX
  CALL BIN2HEXB
  MOV AL,']'
  STOSB
  INC DI
  RET

SHOBYTE:
  PUSH DI
  MOV AL,INSTRATTRIB
  CMP MODE,7
  IF Z MOV AL,070
  MOV AH,'_'
  MOV DI,SCRNCUR
  CMP B ES:[DI-1],0
  IF Z MOV ES:[DI-1],AH
  CMP B ES:[DI-1],020
  IF Z MOV ES:[DI-1],AH
  CMP B ES:[DI-1],0FF
  IF Z MOV ES:[DI-1],AH
  STOSB 	;HILITE BYTE
  POP DI
  ADD SCRNCUR,2
  RET

SHOWORD:
  PUSH DI
  MOV AL,INSTRATTRIB
  CMP MODE,7
  IF Z MOV AL,070
  MOV AH,'_'
  MOV DI,SCRNCUR
  CMP B ES:[DI-1],0
  IF Z MOV ES:[DI-1],AH
  CMP B ES:[DI-1],020
  IF Z MOV ES:[DI-1],AH
  CMP B ES:[DI-1],0FF
  IF Z MOV ES:[DI-1],AH
  STOSB 	;HILITE BYTE
  INC DI
  CMP B ES:[DI-1],0
  IF Z MOV ES:[DI-1],AH
  CMP B ES:[DI-1],020
  IF Z MOV ES:[DI-1],AH
  CMP B ES:[DI-1],0FF
  IF Z MOV ES:[DI-1],AH
  STOSB 	;DITTO
  POP DI
  ADD SCRNCUR,4
  SUB BP,BP
  RET

OLDSCR EQU $
PREBUF EQU OLDSCR +0FB0  ;4000D + 10H = (25*80) + ROOM TO ZERO LOW NIBBLE

[ RETURN TO DIRECTORY ]