
.cs 5
.mt 5
.mb 6
.pl 66
.ll 65
.po 10
.hm 2
.fm 2
.he
.bp
.tc    5.3  A Sample File-to-File Copy Program
.he CP/M Operating System Manual           5.3  A Sample Copy Program
.sh
5.3  A Sample File-to-File Copy Program
.qs
.pp
The following program provides a relatively simple example of file
operations.  The program source file is created as COPY.ASM using 
the CP/M ED program and then assembled using ASM or MAC, resulting 
in a HEX file.  The LOAD program is used to produce a COPY.COM 
file that executes directly under the CCP.  The program begins 
by setting the stack pointer to a local area and proceeds to move 
the second name from the default area at 006CH to a 33-byte File 
Control Block called DFCB.  The DFCB is then prepared for file 
operations by clearing the current record  field.  At this point, 
the source and destination FCBs are ready for processing, because 
the SFCB at 005CH is properly set up by the CCP upon entry to the 
COPY program.  That is, the first name is placed into the default 
FCB, with the proper fields zeroed, including the current record 
field at 007CH.  The program continues by opening the source 
file, deleting any existing destination file, and creating the destination
file.  If all this is successful, the program loops at the label
COPY until each record is read from the source file and placed into the 
destination file.  Upon completion of the data transfer, the
destination file is closed and the program returns to the
CCP command level by jumping to BOOT.
.ll 75
.sp 3
.nf
                            ;        sample file-to-file copy program
                            ;
                            ;        at the ccp level, the command
                            ;
                            ;             copy a:x.y b:u.v
                            ;
                            ;        copies the file named x.y from drive
                            ;        a to a file named u.v. on drive b.
                            ;
0000 =                      boot     equ 0000h      ;system reboot
0005 =                      bdos     equ 0005h      ;bdos entry point
005c =                      fcbl     equ 005ch      ;first file name
005c =                      sfcb     equ fcbl       ;source fcb
006c =                      fcb2     equ 006ch      ;second file name
0080 =                      dbuff    equ 0080h      ;default buffer
0100 =                      tpa      equ 0100h      ;beginning of tpa
                            ;
0009 =                      printf   equ 9          ;print buffer func#
000f =                      openf    equ 15         ;open file func#
0010 =                      closef   equ 16         ;close file func#
0013 =                      deletef  equ 19         ;delete file func#
0014 =                      readf    equ 20         ;sequential read
0015 =                      writef   equ 21         ;sequential write
0016 =                      makef    equ 22         ;make file func#
                            ;
0100                                 org tpa        ;beginning of tpa
0100 311b02                          lxi sp,stack   ;local stack
                            ;
                            ;        move second file name to dfcb
0103 0e10                            mvi c,16       ;half an fcb
0105 116c00                          lxi d,fcb2     ;source of move
0108 21da01                          lxi h,dfcb     ;destination fcb
010b 1a                     mfcb:    Idax d         ;source fcb
010c 13                              inx  d         ;ready next
010d 77                              mov  m,a       ;dest fcb
010e 23                              inx  h         ;ready next
010f 0d                              dcr  c         ;count 16...0
0110 c10b01                          jnz  mfcb      ;loop 16 times
                            ;
                            ;        name has been removed, zero cr
0113 af                              xra  a         ;a = 00h
0114 32fa01                          sta  dfcbcr    ;current rec = 0
                            ;
                            ;        source and destination fcb's ready
                            ;
0117 115c00                          lxi  d,sfcb    ;source file
011a cd6901                          call open      ;error if 255
011d 118701                          lxi  d,nofile  ;ready message
0120 3c                              inr  a         ;255 becomes 0
0121 cc6101                          cz   finis     ;done if no file
                            ;
                            ;        source file open, prep destination
0124 11da01                          lxi  d,dfcb    ;destination
0127 cd7301                          call delete    ;remove if present
                            ;
012a 11da01                          lxi  d,dfcb    ;destination
012d cd8201                          call make      ;create the file
0130 119601                          lxi  d,nodir   ;ready message
0133 3c                              inr  a         ;255 becomes 0
0134 cc6101                          cz   finis     ;done if no dir space
                            ;
                            ;        source file open, dest file open
                            ;        copy until end of file on source
                            ;
0137 115c00                 copy:    lxi  d,sfcb    ;source
013a cd7801                          call read      ;read next record
013d b7                              ora  a         ;end of file?
013e c25101                          jnz  eofile    ;skip write if so
                            ;
                            ;        not end of file, write the record
0141 11da01                          lix  d,dfcb    ;destination
0144 cd7d01                          call write     ;write record
0147 11a901                          lxi  d,space   ;ready message
014a b7                              ora  a         ;00 if write ok
014b c46101                          cnz  finis     ;end if so
014e c33701                          jmp  copy      ;loop until eof
                            ;
                            eofile:  ;end of file, close destination
0151 11da01                          lxi  d,dfcb    ;destination
0154 cd6e01                          call close     ;255 if error
0157 21bb01                          lxi  h,wrprot  ;ready message
015a 3c                              inr  a         ;255 becomes 00
015b cc6101                          cz   finis     ;shouldn't happen
                            ;
                            ;        copy operation complete, end
015e 11cc01                          lxi  d,normal  ;ready message
                            ;
                            finis    ;write message given by de, reboot
0161 0e09                            mvi  c,printf
0163 cd0500                          call bdos      ;write message
0166 c30000                          jmp  boot      ;reboot system
                            ;
                            ;        system interface subroutines
                            ;        (all return directly from bdos)
                            ;
0169 0e0f                   open:    mvi  c,openf
016b c30500                          jmp  bdos
                            ;
016e 0e10                   close:   mvi  c,closef
0170 c30500                          jmp  bdos
                            ;
0173 0e13                   delete   mvi  c,deletef
0175 c30500                          jmp  bdos
                            ;
0178 0e14                   read:    mvi  c,readf
017a c30500                          jmp  bdos
                            ;
017d 0e15                   write:   mvi  c,writef
017f c30500                          jmp  bdos
                            ;
0182 0e16                   make:    mvi  c,makef
0184 c30500                          jmp  bdos
                            ;
                            ;        console messages
0187 6e6f20f                nofile:  db   'no source file$'
0196 6e6f209                nodir:   db   'no directory space$'
01a9 6f7574f                space:   db   'out of dat space$'
01bb 7772695                wrprot:  db   'write protected?$'
01cc 636f700                normal:  db   'copy complete$'
                            ;
                            ;        data areas
01da                        dfcb:    ds   33        ;destination fcb
01fa                        dfcbcr   equ  dfcb+32   ;current record
                            ;
01fb                                 ds   32        ;16 level stack
                            stack:
021b                                 end
.ll 65
.fi
.in 0
.sp 2
.pp
Note that there are several simplifications in this
particular program.  First, there are no checks for invalid filenames
that could contain ambiguous references.  This
situation could be detected by scanning the 32-byte default area 
starting at location 005CH for ASCII question marks.  A check 
should also be make to ensure that the filenames have 
been included (check locations 005DH and 006DH for nonblank ASCII 
characters).  Finally, a check should be made to ensure that the 
source and destination filenames are different.  An improvement 
in speed could be obtained by buffering more data on each read 
operation.  One could, for example, determine the size of memory 
by fetching FBASE from location 0006H and using the entire 
remaining portion of memory for a data buffer.  In this case, the 
programmer simply resets the DMA address to the next successive 
128-byte area before each read.  Upon writing to the destination 
file, the DMA address is reset to the beginning of the buffer and 
incremented by 128 bytes to the end as each record is 
transferred to the destination file.
.sp 2
.he CP/M Operating System Manual      5.4  A Sample File Dump Utility
.tc    5.4  A Sample File Dump Utility
.sh
5.4  A Sample File Dump Utility
.qs
.pp
The following file dump program is slightly more complex than 
the simple copy program given in the previous section.  The dump 
program reads an input file, specified in the CCP command line, 
and displays the content of each record in hexadecimal format at 
the console.  Note that the dump program saves the CCP's stack 
upon entry, resets the stack to a local area, and restores the 
CCP's stack before returning directly to the CCP.  Thus, the 
dump program does not perform and warm start at the end of 
processing.
.ll 75
.sp 3
.nf
x.in 5
                            ;DUMP program reads input file and displays
                            hex data
                            ;
0100                                 org  100h
0005 =                      bdos     equ  0005h =   ;bdos entry point
0001 =                      cons     equ  1         ;read console
0002 =                      typef    equ  2         ;type function
0009 =                      printf   equ  9         ;buffer print entry
000b =                      brkf     equ  11        ;break key function
                                                    ;(true if char
000f =                      openf    equ  15        ;file open
0014 =                      readf    equ  20        ;read function
                            ;
005c =                      fcb      equ  5ch       ;file control block
                                                    ;address
0080 =                      buff     equ  80h       ;input disk buffer
                                                    ;address
                            ;
                            ;        non graphic characters
000d =                      cr       equ  0dh       ;carriage return
000a =                      If       equ  0ah       ;line feed
                            ;
                            ;        file control block definitions
005c =                      fcbdn    equ  fcb+0     ;disk name
005d =                      fcbfn    equ  fcb+1     ;file name
0065 =                      fcbft    equ  fcb+9     ;disk file type (3
                                                    ;characters)
0068 =                      fcbrl    equ  fcb+12    ;file's current reel
                                                    ;number
006b =                      fcbrc    equ  fcb+15    ;file's record count (0 to
                                                    ;128)128)
007c =                      fcbcr'   equ  fcb+32    ;current (next) record
                                                    ;number (0
007d =                      fcbin    equ  fcb+33    ;fcb length
                            ;
                            ;        set up stack
0100 210000                          lxi  h,0
0103 39                              dad  sp
                            ;        entry stack pointer in hl from the ccp
0104 221502                          shld oldsp
                            ;        set sp to local stack area (restored at
                            ;        finis)
0107 315702                          lxi  sp,stktop
                            ;        read and print successive buffers
010a cdc101                          call setup     ;set up input file
010d feff                            cpi  255       ;255 if file not present
010f c21b01                          jnz  openok    ;skip if open is ok
                            ;
                            ;        file not there, give error message and
                            ;        return
0112 11f301                          lxi  d,opnmsg
0115 cd9c01                          call err
0118 c35101                          jmp finis      ;to return
                            ;
                            openok:  ;open operation ok, set buffer index to
                                     ;end
011b 3e80                            mvi  a,80h
011d 321302                          sta  ibp       ;set buffer pointer to 80h
                            ;        hl contains next address to print
0120 210000                          lxi  h,0       ;start with 0000
                            ;
                            gloop:
0123 e5                              push h         ;save line position
0124 cda201                          call gnb
0127 e1                              pop  h         ;recall line position
0138 da5101                          jc   finis     ;carry set by gnb if end
                                                    ;file
012b 47                              mov  b,a
                            ;        print hex values
                            ;        check for line fold
012c 7d
                                     mov  a,l
012d e60f                            ani  0fh       ;check low 4 bits
012f c24401                          jnz nonum
                            ;        print line number
0132 cd7201                          call crlf
                            ;
                            ;        check for break key
0135 cd5901                          call break
                            ;        accum lsb = 1 if character ready
0138 0f                              rrc            ;into carry
0139 da5101                          jc   finis     ;don't print any more
                            ;
013c 7c                              mov  a,h
013d cd8f01                          call phex
0140 7d                              mov  a,l
0141 cd8f01                          call phex
                            nonum
0144 23                              inx  h         ;to next line number
0145 3e20                            mvi  a,''
0147 cd6501                          call pchar
014a 78                              mov  a,b
014b cd8f01                          call phex
014e c32301                          jmp  gloop
                            ;
                            finis
                            ;        end of dump, return to cco
                            ;        (note that a jmp to 0000h reboots)
0151 cd7201                          call crif
0154 2a1502                          lhld oldsp
0157 f9                              sphl
                            ;        stack pointer contains ccp's stack
                            ;        location
0158 c9                              ret            ;to the ccp
                            ;
                            ;
                            ;        subroutines
                            ;
                            break:   ;check break key (actually any key will
                                     ;do)
0159 e5d5c5                          push h! push d! push b; environment
                                     ;saved
015c 0e0b                            mvi  c,brkf
015e cd0500                          call bdos
0161 c1d1e1                          pop b! pop d! pop h; environment
                                     restored
0164 c9                              ret
                            ;
                            pchar:   ;print a character
0165 e5d5c5                          push h! push d! push b; saved
0168 0e02                            mvi  c, typef
016a 5f                              mov  e,a
016b cd0500                          call bdos
016e c1d1e1                          pop b! pop d! pop h; restored
0171 c9                              ret
                            ;
                            crlf
0172 3e0d                            mvi  a,cr
0174 cd6501                          call pchar
0177 3e0a                            mvi  a,lf
0179 cd6501                          call pchar
017c c9                              ret
                            ;
                            ;
                            pnib:    ;print nibble in reg a
017d e60f                            ani  ofh       ;low 4 bits
017f fe0a                            cpi  10
0181 d28901                          jnc  p10
                            ;        less than or equal to 9
0184 c630                            adi  '0'
0186 c38b01                          jmp  prn
                            ;
                            ;        greater or equal to 10
0189 c637                   p10:     adi  'a' - 10
018b cd6501                 prn:     call pchar
018e c9                              ret
                            ;
                            phex     ;print hex char in reg a
018f f5                              pushpsw
0190 0f                              rrc
0191 0f                              rrc
0192 0f                              rrc
0193 0f                              rrc
0194 cd7d01                          call pnib      ;print nibble
0197 f1                              pop  psw
0198 cd7d01                          call pnip
019b c9                              ret
                            ;
                            err:     ;print error message
                            ;        d,e addresses message ending with "$"
019c 0e09                            mvi  c,printf  ;print buffer
                                                    ;function
019e cd0500                          call bdos
01a1 c9                              ret
                            ;
                            ;
                            gnb:     ;get next byte
01a2 3a1302                          lda  ibp
01a5 fe80                            cpi  80h
01a7 c2b301                          jnz  g0
                            ;        read another buffer
                            ;
                            ;
 01aa cdce01                         call diskr
01ad b7                              ora  a         ;zero value if read ok
01ae cab301                          jz   g0        ;for another byte
                            ;        end of data, return with carry set for eof
01b1 37                              stc
01b2 c9                              ret
                            ;
                            g0:      ;read the byte at buff+reg a
01b3 5f                              mov  e,a       ;Is byte of buffer index
01b4 1600                            mvi  d,0       ;double precision
                                                    ;index to de
01b6 3c                              inr  a         ;index=index+1
01b7 321302                          sta  ibp       ;back to memory
                            ;        pointer is incremented
                            ;        save the current file address
01ba 218000                          lxi  h,buff
01bd 19                              dad  d
                            ;        absolute character address is in hl
01be 7e                              mov  a,m
                            ;        byte is in the accumulator
01bf b7                              ora  a         ;reset carry bit
01c0 c9                              ret
                            ;
                            setup:   ;set up file
                            ;        open the file for input
01c1 af                              xra  a         ;zero to accum
01c2 327c00                          sta  fcbcr     ;clear current record
                            ;
01c5 115c00                          lxi  d,fcb
01c8 0e0f                            mvi  c,openf
01ca cd0500                          call bdos
                            ;        255 in accum if open error
01cd c9                              ret
                            ;
                            diskr:   ;read disk file record
01ce e5d5c5                          push h! push d! push b
01d1 115c00                          lxi  d,fcb
01d4 0e14                            mvi  c,readf
01d6 cd0500                          call bdos
01d9 c1d1e1                          pop b! pop d! pop h
01dc c9                              ret
                            ;
                            ;        fixed message area
01dd 46494c0                signon:  db   'file dump version 2.0$'
01f3 0d0a4e0                opnmsg:  db   cr,lf,'no  input file present on
                                          disk$'

                            ;        variable area
0213                        ibp:     ds   2         ;input buffer pointer
0215                        oldsp:   ds   2         ;entry sp value from ccp
                            ;
                            ;        stack area
0217                        ;        ds   64        ;reserve 32 level stack
                            stktop:
                            ;
0257                                 end
.ll 65
.fi
.in 0
.nx fived
