;
; +++++++ 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
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