.sp 2
.tc    4.4  A Sample Program
.he CP/M Operating System Manual                4.4  A Sample Program
.sh
4.4  A Sample Program
.pp
The following example shows an edit, assemble, and debug for a 
simple program that reads a set of data values and determines the 
largest value in the set.  The largest value is taken from the 
vector and stored into LARGE at the termination of the program.
.ll 75
.sp 2
.nf
A>\c
.sh
ED SCAN.ASM                \c
.qs
Create source program;
                             " " represents carriage return.
*I
                ORG          1-00H          ;START OF TRANSIENT
                                            ;AREA
                MVI          B, LEN         ;LENGTH OF VECTOR TO SCAN
                MVI          C, 0           ;LARGER_RST VALUE SO FAR
LOOP            LXI          H, VECT        ;BASE OF VECTOR
LOOP:           MOV          A, M           ;GET VALUE
                SUB          C              ;LARGER VALUE IN C?
                JNC          NFOUND         ;JUMP IF LARGER VALUE NOT
                                            ;FOUND
;               NEW LARGEST VALUE, STORE IT TO C
                MOV          C, A
NFOUND          INX          H              ;TO NEXT ELEMENT
                DCR          B              ;MORE TO SCAN?
                JNZ          LOOP           ;FOR ANOTHER
;
;               END OF SCAN, STORE C
                MOV          A, C           ;GET LARGEST VALUE
                STA          LARGE
                JMP          0              ;REBOOT
;
;               TEST DATA
VECT:           DB           2,0,4,3,5,6,1,5
LEN             EQU          $-VECT         ;LENGTH
LARGE:          DS           1              ;LARGEST VALUE ON EXIT
                END

.bp
^-Z
*B0P
                ORG          100H           ;START OF TRANSIENT AREA
                MVI          B,LEN          ;LENGTH OF VECTOR TO SCAN
                MVI          C,0            ;LARGEST VALUE SO FAR
                LXI          H,VECT         ;BASE OF VECTOR
LOOP:           MOV          A,M            ;GET VALUE
                SUB          C              ;LARGER VALUE IN C?
                JNC          NFOUND         ;JUMP IF LARGER VALUE NOT
                                            ;FOUND
;               NEW LARGEST VALUE, STORE IT TO C
                MOV          C,A
NFOUND:         INX          H              ;TO NEXT ELEMENT
                DCR          B              ;MORE TO SCAN?
                JNZ          LOOP           ;FOR ANOTHER
;               END OF SCAN, STORE C
                MOV          A,C            ;GET LARGEST VALUE
                STA          LARGE
                JMP          0              ;REBOOT
;
;               TEST DATA

VECT:           DB           2,0,4,3,5,6,1,5
LEN             EQU          $-VECT         ;LENGTH
LARGE:          DS           1              ;LARGEST VALUE ON EXIT
                END
*E <--End of edit

A>\c
.sh
ASM SCAN     \c
.qs
Start Assembler

CP/M ASSEMBLER - VER 1.0

0122
002H USE FACTOR
END OF ASSEMBLY     Assembly complete; lock at program listing

A>\c
.sh
TYPE SCAN.PRN
.qs
 Code address   Source program
 0100                        ORG 100H       ;START OF TRANSIENT AREA
 0100    0608                MVI B,LEN      ;LENGTH OF VECTOR TO SCAN
 0102    0E00 Machine code   MVI C,0        ;LARGEST VALUE SO FAR
 0104    211901              LXI H,VECT.    ;BASE OF VECTOR
 0107    7E          LOOP:   MOV A,M        ;GET VALUE
 0108    91                  SUB C          ;LARGER VALUE IN C?
 0109    D20D01              JNC NFOUND     ;JUMP IF LARGER VALUE NOT
                                            ;FOUND
                     ;       NEW LARGEST VALUE, STORE IT TO C
 010C    4F                  MOV C,A
.bp
 010D    23          NFOUND: INX H          ;TO NEXT ELEMENT
 010E    05                  DCR  B         ;MORE TO SCAN?
 010F    C20701              JNZ LOOP       ;FOR ANOTHER
                     ;
                     ;       END OF SCAN, STORE C
 0112    79                  MOV A,C        ;GET LARGEST VALUE
 0113    322101              STA LARGE

 0116    C30000              JMP 0          ;REBOOT
   Code--data listing;
   truncated         ;       TEST DATA
 0119    0200040305  VECT:   DB 2,0,4,3,5,6,1,5
 0008    = Value of  LEN     EQU $-VECT     ;LENGTH
 0121      equate    LARGE:  DS 1           ;LARGEST VALUE ON EXIT
 0122                        END


A>\c
.sh
DDT SCAN.HEX      \c
.qs
Start debugger using hex format machine code

DDT VER 1.0
NEXT PC                                              Next instruction
0121 0000                                            to execute at
-X     Last load address + 1                         PC=0

C0Z0M0E0I0 A=00 B=0000 D=0000 H=0000 S=0100 P=0000 OUT 7F
-XP                 Examine registers before debug run

P=0000 100    Change PC to 100

-X    Look at registers again

C0Z0M0E0I0 A=00 B=0000 D=0000 H=0000 S=0100 P=0100 MVI B,08
-L100
                              PC changed      Next instruction
                                              to execute at PC=100
 0100   MVI        B,08
 0102   MVI        C,00
 0104   LXI        H,0119
 0107   MOV        A,M
 0108   SUB        C          Disassembled machine
 0109   JNC        010D       code at 100H
 010C   MOV        C,A        (see source listing
 010D   INX        H          for comparison)
 010E   DCR        B
 010F   JNZ        0107
 0112   MOV        A,C
-L
.bp
 0113   STA        0121
 0116   JMP        0000
 0119   STAX       B
 011A   NOP                   A little more machine
 011B   INR        B          code.  Note that pro-
 011C   INX        B          gram ends at location
 011D   DCR        B          116 with a JMP to
 011E   MVI        B,01       0000.  Remainder of
 0120   DCR        B          listing is assembly of
 0121   LXI        D,2200     data.
 0124   LXI        H,0200
-A116  Enter in-line assembly mode to change the JMP to 0000 into a RST 7,
       which will cause the program under test to return to DDT if 116H is
       ever executed.
0116 RST 7

0117   (Single carriage return stops assemble mode)

-L113   List code at 113H to check that RST 7 was properly inserted

 0113   STA        0121
 0116   RST        07    in place of JMP
 0117   NOP
 0118   NOP
 0119   STAX       B
 011A   NOP
 011B   INR        B
 011C   INX        B
-

-X    Look at registers

C0Z0M0E0I0 A=00 B=0000 D=0000 H=0000 S=0100 P=0100 MVI B,08
-T
   Execute Program for one stop. Initial CPU state, before   is executed

C0Z0M0E0I0 A=00 B=0000 D=0000 H=0000 S=0100 P=0100 MVI B,08*0102
                                       Automatic breakpoint

     Trace one step again (note O8H in B)
C0Z0M0E0I0 A=00 B=0800 D=0000 H=0000 S=0100 P=0102 MVI C,00*0104
-T
     Trace again (Register C is cleared)
C0Z0M0E0I0 A=00 B=0800 D=0000 H=0000 S=0100 P=0104 LXI H,0119*0107
-T3  Trace three steps
C0Z0M0E0I0 A=00 B=0800 D=0000 H=0119 S=0100 P=0107 MOV A,M
C0Z0M0E0I0 A=02 B=0800 D=0000 H=0119 S=0100 P=0108 SUB C
C0Z0M0E0I1 A=02 B=0800 D=0000 H=0119 S=0100 P=0109 JNC 010D*010D
-D119
       Display memory starting at 119H. Automatic breakpoint at 10DH

0119 02 00 04 03 05 06 01.Program data         Lower-case x
0120 05 11 00 22 21 00 02 7E EB 77 13 23 EB 0B 78 B1 ..."!.. . W .#..X.
0130 C2 27 01 C3 03 29 00 00 00 00 00 00 00 00 00 00 ...' ...).........
0140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ..................
0150 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ..................
0160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 Data are displayed
0170 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 in ASCI with a "."
0180 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 in the position of
0190 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 nongraphic........
01A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 characters........
01B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ..................
01C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ..................
-X
           Current CPU state
C0Z0M0E0I1 A=02 B=0800 D=0000 H=0119 S=0100 P=010D INX H
-T5
     Trace 5 steps from current CPU state
C0Z0M0E0I1 A=02 B=0800 D=0000 H=0119 S=0100 P=010D INX H
C0Z0M0E0I1 A=02 B=0800 D=0000 H=011A S=0100 P=010E DCR B
C0Z0M0E0I1 A=02 B=0700 D=0000 H=011A S=0100 P=010F JNZ 0107
C0Z0M0E0I1 A=02 B=0700 D=0000 H=011A S=0100 P=0107 MOV A,M
C0Z0M0E0I1 A=00 B=0700 D=0000 H=011A S=0100 P=0108 SUB C*0109

U5
                                   Automatic breakpoint
     Trace without listing intermediate states
C0Z1M0E1I1 A=00 B=0700 D=0000 H=011A S=0100 P=0109 JNC 010D*0108
-X
                       CPU state at end of U5
C0Z0M0E1I1 A=04 B=0600 D=0000 H=011B S=0100 P=0108 SUB C
-G   Run program from current PC until completion (in real-time)

*0116   breakpoint at 116H, caused by executing RST 7 in machine code.

-X
     CPU state at end of program
C0Z1M0E1I1 A=00 B=0000 D=0000 H=0121 S=0100 P=0116 RST 07
-XP
     Examine and change program counter

P=0116 100

-X

C0Z1M0E1I1 A=00 B=0000 D=0000 H=0121 S=0100 P=0100 MVI B,08
-T10

                            First data element
                                   Current largest value
                                          Subtract for comparison C
    Trace 10 (hexadecimal) steps
C0Z1M0E1I1 A=00 B=0800 D=0000 H=0121 S=0100 P=0100 MVI B,08
C0Z1M0E1I1 A=00 B=0000 D=0000 H=0121 S=0100 P=0102 MVI C,00
C0Z1M0E1I1 A=00 B=0800 D=0000 H=0121 S=0100 P=0104 LXI H,0119
C0Z1M0E1I1 A=00 B=0800 D=0000 H=0119 S=0100 P=0107 MOV A,M
C0Z1M0E1I1 A=02 B=0800 D=0000 H=0119 S=0100 P=0108 SUB C
C0Z0M0E0I1 A=02 B=0800 D=0000 H=0119 S=0100 P=0109 JNC 010D
C0Z0M0E0I1 A=02 B=0800 D=0000 H=0119 S=0100 P=010D INX H
C0Z0M0E0I1 A=02 B=0800 D=0000 H=011A S=0100 P=010E DCR B
C0Z0M0E0I1 A=02 B=0700 D=0000 H=011A S=0100 P=010F JNZ 0107
C0Z0M0E0I1 A=02 B=0700 D=0000 H=011A S=0100 P=0107 MOV A,M
C0Z0M0E0I1 A=00 B=0700 D=0000 H=011A S=0100 P=0108 SUB C
C0Z1M0E1I1 A=00 B=0700 D=0000 H=011A S=0100 P=0109 JNC 010D
C0Z1M0E1I1 A=00 B=0700 D=0000 H=011A S=0100 P=010D INX H
C0Z1M0E1I1 A=00 B=0700 D=0000 H=011B S=0100 P=010E DCR B
C0Z0M0E1I1 A=00 B=0600 D=0000 H=011B S=0100 P=010F JNZ 0107
C0Z0M0E1I1 A=00 B=0600 D=0000 H=011B S=0100 P=0107 MOV A,M*0108
-A109
             Insert a "hot patch" into    Program should have moved the
             the machine code             value from A into C since A>C.
0109 JC 10D  to change the                Since this code was not executed,
             JNC to JC                    it appears that the JNC should
010C                                      have been a JC instruction

       Stop DDT so that a version of
-G0    the patched program can be saved

A>\c
.sh
SAVE 1 SCAN.COM  \c
.qs
Program resides on first
                   page, so save 1 page.
A>\c
.sh
DDT SCAN.COM
.qs
                   Restart DDT with the save memory
DDT VER 1.0        image to continue testing
NEXT PC
0200 0100

-L100    List some code

 0100    MVI B,08
 0102    MVI C,00
 0104    LXI H,0119
 0107    MOV A,M
 0108    SUB C
 0109    JC  010D    Previous patch is present in X.COM
 010C    MOV C,A
 010D    INX H
 010E    DCR B
 010F    JNZ 0107
 0112    MOV A,C
 -XP

P=0100

-T10
     Trace to see how patched version operates    Data is moved from A to C
C0Z0M0E0I0 A=00 B=0000 D=0000 H=0000 S=0100 P=0100 MVI B,08
C0Z0M0E0I0 A=00 B=0800 D=0000 H=0000 S=0100 P=0102 MVI C,00
C0Z0M0E0I0 A=00 B=0800 D=0000 H=0000 S=0100 P=0104 LXI H,0119
C0Z0M0E0I0 A=00 B=0800 D=0000 H=0119 S=0100 P=0107 MOV A,M
C0Z0M0E0I0 A=02 B=0800 D=0000 H=0119 S=0100 P=0108 SUB C
C0Z0M0E0I1 A=02 B=0800 D=0000 H=0119 S=0100 P=0109 JC  010D
C0Z0M0E0I1 A=02 B=0800 D=0000 H=0119 S=0100 P=010C MOV C,A
C0Z0M0E0I1 A=02 B=0802 D=0000 H=0119 S=0100 P=010D INX H
C0Z0M0E0I1 A=02 B=0802 D=0000 H=011A S=0100 P=010E DCR B
C0Z0M0E0I1 A=02 B=0702 D=0000 H=011A S=0100 P=010F JNZ 0107
C0Z0M0E0I1 A=02 B=0702 D=0000 H=011A S=0100 P=0107 MOV A,M
C0Z0M0E0I1 A=00 B=0702 D=0000 H=011A S=0100 P=0108 SUB C
C1Z0M1E0I0 A=FE B=0702 D=0000 H=011A S=0100 P=0109 JC  010D
C1Z0M1E0I0 A=FE B=0702 D=0000 H=011A S=0100 P=010D INX H
C1Z0M1E0I0 A=FE B=0702 D=0000 H=011B S=0100 P=010E DCR B
C1Z0M0E1I1 A=FE B=0602 D=0000 H=011B S=0100 P=010F JNZ 0107*0107
-X                                  Breakpoint after 16 steps

C1Z0M0E1I1 A=FE B=0602 D=0000 H=011B S=0100 P=0107 MOV A,M
-G,108   Run from current PC and breakpoint at 108H

*0108
-X
                Next data item
C1Z0M0E1I1 A=04 B=0602 D=0000 H=011B S=0100 P=0108 SUB C
-T
    Single step for a few cycles
C1Z0M0E1I1 A=04 B=0602 D=0000 H=011B S=0100 P=0108 SUB C*0109
-T

C0Z0M0E0I1 A=02 B=0602 D=0000 H=011B S=0100 P=0109 JC 010D*010C
-X

C0Z0M0E0I1 A=02 B=0602 D=0000 H=011B S=0100 P=010C MOV C,A
-G   Run to completion

*0116
-X

C0Z1M0E1I1 A=03 B=0003 D=0000 H=0121 S=0100 P=0116 RST 07
-S121   Look at the value of "LARGE"

 0121   03   Wrong value!

 0122   00

 0123   22

 0124   21

 0125   00

 0126   02

 0127   7E  _\b.    End of the S command

-L100

 0100   MVI        B,08
 0102   MVI        C,00
 0104   LXI        H,0119
 0107   MOV        A,M
 0108   SUB        C
 0109   JC         010D
 010C   MOV        C,A
 010D   INX        H
 010E   DCR        B
 010F   JNZ        0107
 0112   MOV        A,C
-L                            Review the code

 0113   STA        0121
 0116   RST        07
 0117   NOP
 0118   NOP
 0119   STAX       B
 011A   NOP
 011B   INR        B
 011C   INX        B
 011D   DCR        B
 011E   MVI        B,01
 0120   DCR        B
-XP

P=0116 100   Reset the PC

-T
    Single step, and watch data values
C0Z1M0E1I1 A=03 B=0003 D=0000 H=0121 S=0100 P=0100 MVI B,08*0102
-T

C0Z1M0E1I1 A=03 B=0803 D=0000 H=0121 S=0100 P=0102 MVI C,00*0104
-T
         Count set     Largest set
C0Z1M0E1I1 A=03 B=0800 D=0000 H=0121 S=0100 P=0104 LXI H,0119*0107
-T
                                    Base address of data set
C0Z1M0E1I1 A=03 B=0800 D=0000 H=0119 S=0100 P=0107 MOV A,M*0108
-T
                 First data item brought to A
C0Z1M0E1I1 A=02 B=0800 D=0000 H=0119 S=0100 P=0108 SUB C*0109
-T

C0Z0M0E0I1 A=02 B=0800 D=0000 H=0119 S=0100 P=0109 JC 010D*010C
-T

C0Z0M0E0I1 A=02 B=0800 D=0000 H=0119 S=0100 P=010C MOV C,A*010D
-T
                       First data item moved to C correctly
C0Z0M0E0I1 A=02 B=0802 D=0000 H=0119 S=0100 P=010D INX H*010E
-T

C0Z0M0E0I1 A=02 B=0802 D=0000 H=011A S=0100 P=010E DCR B*010F
-T

C0Z0M0E0I1 A=02 B=0702 D=0000 H=011A S=0100 P=010F JNZ 0107*0107
-T

C0Z0M0E0I1 A=02 B=0702 D=0000 H=011A S=0100 P=0107 MOV A,M*0108
-T
                 Second data item brought to A
C0Z0M0E0I1 A=00 B=0702 D=0000 H=011A S=0100 P=0108 SUB C*0109
-T
                 Subtract destroys data value that was loaded!
C1Z0M1E0I0 A=FE B=0702 D=0000 H=011A S=0100 P=0109 JC 010D*010D
-T

C1Z0M1E0I0 A=FE B=0702 D=0000 H=011A S=0100 P=010D INX H*010E
-L100

 0100   MVI        B,08
 0102   MVI        C,00
 0104   LXI        H,0119
 0107   MOV        A,M
 0108   SUB        C       This should have been a CMP so that register A
 0109   JC         010D    would not be destroyed.
 010C   MOV        C,A
 010D   INX        H
 010E   DCR        B
 010F   JNZ        0107
 0112   MOV        A,C
 -A108

0108 CMP C    Hot patch at 108H changes SUB to CMP

0109

-G0   Stop DDT for SAVE

A>\c
.sh
SAVE 1 SCAN.COM    \c
.qs
Save memory image

A>\c
.sh
DDT SCAN.COM    \c
.qs
Restart DDT

DDT VER 1.0
NEXT PC
0200 0100
-XP

P=0100

-L116
.mb 5
.fm 1

 0116   RST        07
 0117   NOP
 0118   NOP               Look at code to see if it was properly loaded
 0119   STAX       B      (long typeout aborted with rubout)
 011A   NOP
 -

-G,116    Run from 100H to completion

*0116
-XC     Look at carry (accidental typo)
C1
-X   Look at CPU state
.mb 6
.fm 2

C1Z1M0E1I1 A=06 B=0006 D=0000 H=0121 S=0100 P=0116 RST 07
-S121   Look at "large"--it appears to be correct.

0121 06

0122 00

0123 22

-G0    Stop DDT

A>\c
.sh
ED SCAN.ASM    \c
.qs
Re-edit the source program, and make both changes

*NSUB
*0LT
     CTRL-Z        SUB     C           ;LARGER VALUE IN C?
*SSUB^\b|ZCMP^\b|Z0LT
                   CMP     D           ;LARGER VALUE IN C?
*
                   JNC     NFOUND      ;JUMP IF LARGER VALUE NOT FOUND
*SNC^\b|ZC^\b|Z0LT
                   JC      NFOUND      ;JUMP IF LARGER VALUE NOT FOUND
*E
                      Reassemble, selecting source from disk A
A>\c
.sh
ASM SCAN.AAZ   \c
.qs
<--- Hex to disk A
                      Print to Z (selects no print file)
CP/M ASSEMBLER    VER 1.0

0122
002H USE FACTOR
END OF ASSEMBLY

A>\c
.sh
DDT SCAN.HEX    \c
.qs
Rerun debugger to check changes

DDT VER 1.0
NEXT PC
0121 0000
-L116

 0116   JMP        0000     Check to ensure end is still at 116H

 0119   STAX       B

 011A   NOP
 011B   INR        B

 -(rubout)

-G100,116    Go from beginning with breakpoint at end

*0116    Breakpoint reached
-D121    Look at "LARGE"
                      Correct value computed
0121 06 00 22 21 00 02 7E EB 77 13 23 EB 0B 78 B1 .. '!... W .#..X.
0130 C2 27 01 C3 03 29 00 00 00 00 00 00 00 00 00 00 .'...)........
0140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ..............

-(rubout) Aborts long typeout

G0    Stop DDT, debug session complete.
.ll 65
.sp 2
.ce
End of Section 4
.nx fivea
