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