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.
 
 
 
 
 
 

444 lines
23 KiB

.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