You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

583 lines
18 KiB

.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