;
;                    +++++++  LOOK  +++++++
;
;By Kenyon Swartwout
;Reprinted from INTERFACE AGE, May, 1978
;
;This program will look for a byte or a sequence of 2 to 9
;bytes in any program and when found, the address and byte
;will be printed.  If no match is found "NO MATCH" will be
;printed.  Type a "0" when asked for number of bytes to re-
;turn to CP/M.
;
; CP/Mified on 5/16/80 by:
;
;	Kelly Smith
;	Simi Valley, Calif.
;	(805) 527-0518 Verbal
;	(805) 527-9321 Modem
;

;
; CP/M VERSION 1.4 FUNCTION CALL EQUATES
;

RDCON	EQU	1	;READ CONSOLE CHARACTER
WRCON	EQU	2	;WRITE CONSOLE CHARACTER
WRCBUF	EQU	9	;WRITE BUFFER CONTENTS TO CONSOLE

;
; CP/M VERSION 1.4 ADDRESS CONSTANTS
;

BASE	EQU	0
BDOS	EQU	05H+BASE	;ENTRY TO FDOS

;
; DEFINE THE ASCII CONTROL CHARACTERS
;

BEL	EQU	007H	;(^G) BELL
LF	EQU	00AH	;(^J) LINE FEED
CR	EQU	00DH	;(^M) CARRIAGE RETURN



 	ORG	0100H
;
	LXI	H,0	;CLEAR H&L REGS.
	DAD	SP	;ADD STACK POINTER
	SHLD	OLDSTK	;SAVE "OLD" STACK
START:	LXI	SP,NEWSTK	;MAKE "NEW" STACK
	CALL	ZBUF		;ZERO BUFFER
	LXI	D,MSG1
 	CALL	MSGOUT		;OUTPUT 1ST MESSAGE
ST1:	CALL	CONIN
	CPI	'0'
	JZ	CPM	;EXIT TO CP/M IF "0"
	CPI	'1'
	JC	ST1
	CPI	'9'+1
	JNC	ST1
	SUI	48
	MOV	C,A		;SAVE COUNT IN C
	STA	NBR
	STA	NM
	LXI	D,MSG2
	CALL	MSGOUT		;OUTPUT 2ND MESSAGE
	LXI	D,BYTE
	CALL	GET1
	JMP	LK2

LK1:	CALL	CONIN
	STAX	D		;PUT 1ST CHAR IN MEMORY
	INX	D
	CALL	CONIN		;INPUT 2ND CHAR
	STAX	D		;PUT 2ND CHAR IN MEMORY
	DCX	D		;BACK TO 1ST CHAR
	CALL	AHEX		;HEX TO BINARY
	MOV	A,L
	DCX	D
	DCX	D
	STAX	D
	INX	D
	DCR	C
	MVI	A,0
	CMP	C
	RZ			;RETURN WHEN ENTERED
	JMP	LK1		;TO ENTER NEXT BYTE

LK2:	LXI	D,MSG3
	CALL	MSGOUT
	LXI	D,SA
	MVI	C,2
	CALL	LK1		;TO ENTER START ADDR.
	CALL	REV
	LXI	D,MSG4
	CALL	MSGOUT		;OUT FIN. ADDR MESSAGE
	LXI	D,FA
	MVI	C,2
	CALL	LK1		;TO ENTER FINISH ADDR
	CALL	REV
;
;LOOK FOR CHARACTER SEQUENCE
;
	CALL	CRLF
LOOK:	LXI	H,FA		;FINISH ADDR IN H,L
	MOV	C,M
	INX	H
	MOV	B,M
LOOK1:	LXI	D,BYTE
	LHLD	SA
	LDAX	D
	PUSH	PSW
	LDA	NBR
	STA	NUM
	CALL	ENCK		;CHECK FOR FINISH
	POP	PSW
	CMP	M
	JZ	LOOK2
	INX	H
	SHLD	SA		;NEXT ADDR IN SA
	JMP	LOOK1
LOOK2:	INX	H
	SHLD	SA
	DCX	H
LOOK3:	LDA	NUM	;CHECK FOR COMPLETION OF BYTE MATCH
	DCR	A
	STA	NUM
	JZ	PRT
	INX	H
	INX	D
	LDAX	D
	CMP	M
	JZ	LOOK3
	JMP	LOOK1
;
;THIS ROUTINE PRINTS ADDRESS AND MATCHED BYTES
;
PRT:	CALL	CRLF
	MVI	A,BEL	;RING THE BELL...
	CALL	CONOUT
	LHLD	SA
	DCX	H		;ADDR OF OK BYTE
	SHLD	SA
	MOV	A,H		;CONVERT TO HEX & OUT
	PUSH	H
	CALL	HOUT
	POP	H
	MOV	A,L
	CALL	HOUT
	MVI	A,' '
	CALL	CONOUT
	LXI	H,NBR
	MOV	C,M
	LXI	H,BYTE
PRT1:	MOV	A,M
	PUSH	H
	CALL	HOUT
	POP	H
	MVI	A,' '
	CALL	CONOUT
	DCR	C
	PUSH	H
	LXI	H,NM
	MOV	A,C
	MOV	M,C
	POP	H
	MVI	A,0
	CMP	C
	JZ	PRT2		;IF THRU
	INX	H
	JMP	PRT1
PRT2:	LXI	H,NBR	;GET BYTE COUNT
	MOV	C,M
	LHLD	SA	;GET CURRENT MEMORY POINTER
PRT3:	INX	H
	DCR	C
	JNZ	PRT3	;BUMP POINTER PER BYTE COUNT
	SHLD	SA	;SAVE NEW POINTER
	JMP	LOOK

GET1:	CALL	CONIN
	STAX	D		;PUT 1ST CHAR IN MEMORY
	INX	D
	CALL	CONIN		;INPUT 2ND CHAR
	STAX	D		;PUT 2ND CHAR IN MEMORY
	MVI	A,' '
	CALL	CONOUT
	DCX	D		;BACK TO 1ST CHAR
	CALL	AHEX		;HEX TO BINARY
	MOV	A,L
	DCX	D
	DCX	D
	STAX	D
	INX	D
	DCR	C
	MVI	A,0
	CMP	C
	RZ			;RETURN WHEN ENTERED
	JMP	GET1		;TO ENTER NEXT BYTE


MSG1:	DB	CR,LF,CR,LF,'How many bytes (0,1-9)? $'
MSG2:	DB	CR,LF,'List bytes in hex ..... $'
MSG3:	DB	CR,LF,'Start address ......... $'
MSG4:	DB	CR,LF,'Finish address ........ $'
MSG5:	DB	CR,LF,'NO MATCH$'
MSG6:	DB	CR,LF,'$'
;
;THIS ROUTINE CHECKS FOR HL AT FINISH ADDRESS
;
ENCK:	MOV	A,B
	CMP	H
	RNZ			;RETURN IF NOT COMPLETE
	MOV	A,C
	CMP	L
	RNZ			;RETURN IF NOT COMPLETE
	LDA	NM
	CPI	0
	JZ	START	;MATCHING COMPLETED
	LXI	D,MSG5
	CALL	MSGOUT
	CALL	CRLF
	JMP	START
;
;THIS ROUTINE REVERSES 2 BYTES IN MEMORY
;
REV:	DCX	D
	XCHG
	PUSH	B
	MOV	C,M
	DCX	H
	MOV	B,M
	MOV	M,C
	INX	H
	MOV	M,B
	POP	B
	XCHG
	INX	D
	RET
;
;
;
;
;
;THIS ROUTINE CONVERTS A BINARY VALUE TO ASCII
;HEX AND OUTPUTS CHAR.  MEMORY AT HCON.
;
HOUT:	CALL	BINH
	LXI	H,HCON		;CONVERSION AREA
CHOT:	MOV	A,M
	CALL	CONOUT
	INX	H
	MOV	A,M
	CALL	CONOUT
	RET
;
;CONVERTS BINARY VALUE IN REG A TO ASCII HEX
;DIGITS AND STORES IN MEMORY.
;
BINH:	LXI	H,HCON
	MOV	B,A
	RAR
	RAR
	RAR
	RAR
	CALL	BIN1
	MOV	M,A
	INX	H
	MOV	A,B
	CALL	BIN1
	MOV	M,A
	RET
;
;THIS ROUTINE CONVERTS BINARY TO HEX
;
BIN1:	ANI	0FH		;LOW 4 BITS
	ADI	48		;CONVERTS TO ASCII
	CPI	58		;DIGIT 0-9
	RC
	ADI	7		;MODIFY FOR A-F
	RET
;
;THIS ROUTINE FETCHES DIGITS FROM THE
;BUFFER ADDRESSED BY B,C AND CONVERTS
;ASCII HEX DIGITS TO BINARY.  UP TO
;16 BITS CAN BE CONVERTED.  STOPS AT 0.
;
AHEX:	LXI	H,0
AHE1:	LDAX	D		;FETCH ASCII DIGIT
	ORA	A		;SET Z FLAG
	RZ
	DAD	H
	DAD	H
	DAD	H
	DAD	H
	CALL	ASH1		;CONVERT TO BINARY
	CPI	10H		;CHECK FOR LEGAL VALUE
	CMC
	RC			;RETURN IF ERROR
	ADD	L
	MOV	L,A
	INX	D
	JMP	AHE1
;
;CONVERTS ASCII HEX TO BINARY
;
ASH1:	SUI	48		;ASCII BIAS
	CPI	10		;DIGIT 1-10
	RC
	SUI	7		;ALPHA BIAS
	RET
;
;
;THIS ROUTINE ZEROES OUT A BUFFER
;
ZBUF:	MVI	B,ENDZ-STARTZ
	LXI	H,STARTZ
ZBU1:	XRA	A
	MOV	M,A
	INX	H
	DCR	B
	JNZ	ZBU1	;LOOP 'TILL BUFFER ZERO'D
	RET
;

;
; CONSOLE CHARACTER INPUT SUBROUTINE
;
; ENTRY = NONE
; EXIT =  ASCII CHARACTER RETURNS IN A REG.
;
CONIN:	PUSH	H	;SAVE REGISTERS
	PUSH	D
	PUSH	B
	MVI	C,RDCON	;READ CONSOLE
	CALL	BDOS
	POP	B
	POP	D
	POP	H	;RESTORE REGISTERS
	RET

;
; CONSOLE CHARACTER OUTPUT SUBROUTINE
;
; ENTRY = ENTER WITH ASCII CHARACTER IN A REG.
; EXIT = NONE
;
CONOUT:	PUSH	H	;SAVE REGISTERS
	PUSH	D
	PUSH	B
	PUSH	PSW
	MOV	E,A	;CHARACTER TO E REG.
	MVI	C,WRCON	;WRITE CONSOLE FUNCTION
	CALL	BDOS
	POP	PSW
	POP	B
	POP	D
	POP	H	;RESTORE REGISTERS
	RET

;
; PRINT MESSAGE TO CONSOLE SUBROUTINE
;
; ENTER = MESSAGE STRING POINTED TO BY D&E REGS.
; EXIT = NONE
;
MSGOUT:	PUSH	H	;SAVE ALL REGISTERS
	PUSH	B
	PUSH	PSW
	MVI	C,WRCBUF;PRINT CONSOLE BUFFER FUNCTION
	CALL	BDOS
	POP	PSW
	POP	B
	POP	H	;RESTORE REGISTERS
	RET

;
; DISPLAY CARRIAGE RETURN/LINE FEED SUBROUTINE
;
; ENTRY = NONE
; EXIT =NONE
;

CRLF:	PUSH	H	;SAVE ALL REGISTERS
	PUSH	D
	PUSH	B
	PUSH	PSW
	LXI	D,MSG6	;POINT TO CR/LF MESSAGE
	CALL	MSGOUT
	POP	PSW
	POP	B
	POP	D
	POP	H	;RESTORE ALL REGISTERS
	RET		;RETURN FROM "CRLF"

CPM:	LHLD	OLDSTK	;GET "OLD" STACK POINTER
	SPHL		;RESTORE THE STACK POINTER
	RET		;RETURN FROM WHENCE WE CAME...

STAT	EQU	3
DATA	EQU	2
STARTZ	EQU	$	;START OF ZERO'D BUFFER
NBR	DS	1
NUM	DS	1
BYTE	DS	10
HCON	DS	2
NM	DS	1
SA	DS	3
FA	DS	3
ENDZ	EQU	$	;END OF ZERO'D BUFFER
OLDSTK	DS	2	;STORAGE FOR "OLD" STACK
	DS	64	;32 LEVEL STACK
NEWSTK	EQU	$	;STORAGE FOR "NEW" STACK
;
	END
