Files
Digital-Research-Source-Code/CPM OPERATING SYSTEMS/CPM 86/CONCURRENT/CCPM-86 2.0 SOURCE/serializ/serial16.lst
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

1435 lines
75 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

CP/M ASM86 1.1 SOURCE: SERIAL16.A86 PAGE 1
; Use "gencmd serial data[m100]" when producing CMD file
; print control constants
000D cr equ 00Dh ; carriage return
000A lf equ 00Ah ; line feed
0007 bell equ 007h ; self-explanatory
0008 bs equ 008h ; backspace
000B vt equ 00Bh ; vertical tab
; ccpm call function codes
00E0 ccpm equ 224 ; ccpm interrupt
0001 c_read equ 1 ; request single character from console
0002 c_write equ 2 ; send single character to console
0009 c_writebuf equ 9 ; print string terminated by '$'
001F drv_dpb equ 31 ; get DBP offset and segment base
000D drv_resetall equ 13 ; reset disk system
000E drv_set equ 14 ; select disk drive reg DL=disk #
; (0=A,1=B,etc.)
0035 mc_max equ 53 ; find available memory space
; bdos function codes for direct BIOS calls
0032 s_bios equ 50 ; direct BIOS call function code
000D read_code equ 13 ; read a 128 byte sector
000E write_code equ 14 ; write a 128 byte sector
; program constants
00E5 blank equ 0E5h ; data which an empty (blank)
; sector will contain
FFFF false equ -1
0000 true equ 0
cseg
start:
; init serial_number
0000 B90600 mov cx,length ser_def
0003 B030 mov al,'0'
0005 BBA508 mov bx,offset serial_number
initlop10:
0008 8807 mov byte ptr[bx],al
000A 43 inc bx
000B E2FB 0008 loop initlop10
; give sign on
000D E88205 0592 call clear ; clear the monitor screen
0010 BAD902 mov dx,offset msg0 ; print sign on message
0013 E87705 058D call pmsg
CP/M ASM86 1.1 SOURCE: SERIAL16.A86 PAGE 2
; prompt operator for source and destination drives
0016 BAC604 mov dx,offset msg12 ; send source message to
0019 E87105 058D call pmsg ; console
001C E88105 05A0 call get_char ; get disk code
001F 2C41 sub al,'A' ; correct it
0021 A23601 mov dskS,al ; store code for source disk
0024 BAE804 mov dx,offset msg13 ; send destination message
0027 E86305 058D call pmsg ; to console
002A E87305 05A0 call get_char ; get disk code
002D 2C41 sub al,'A' ; correct it
002F A23701 mov dskD,al ; store code for dest disk
; prompt operator for source disk
0032 BA0E05 mov dx,offset msg14 ; send message
0035 E83B05 0573 call pmsg_wait
; the reset function clears out any previous information pertaining
; to format, sector size, density, etc. and the next time a disk is
; selected those values will be reinitialized.
0038 B10D mov cl,drv_resetall ; reset disks
003A CDE0 int ccpm
; when a disk is selected, CP/M initializes the Disk Parameter Header
; and the Disk Parameter Block to conform with the format of the
; selected disk.
003C A03601 mov al,dskS ; select source disk
003F A20601 mov disk,al
0042 B132 mov cl,s_bios
0044 BA0501 mov dx,offset sel_dsk_tab
0047 CDE0 int ccpm
; when the "select disk" function is performed using a direct BIOS call
; the offset of the DPH (in system's extra segment) is returned in the
; BX register. the first word of the DPH is the offset of the sector
; translation table for the system.
0049 891E4A01 mov xlt_offset,bx ; save offset of system's
; sector translation table
; move DPB into program data area
004D FC cld
004E B11F mov cl,drv_dpb ; get system extra segment
0050 CDE0 int ccpm ; value and offset of DPB
0052 06 push es ; save ES value
0053 8BF3 mov si,bx ; init source pointer
0055 8E060900 mov es,data_base
0059 BF3B01 mov di,offset DPB
005C 1F pop ds ; get system extra seg into DS
005D B90F00 mov cx,15 ; init byte counter
0060 F3A4 rep movsb
0062 1E push ds ; save system extra seg value
0063 06 push es ; restore DS value
CP/M ASM86 1.1 SOURCE: SERIAL16.A86 PAGE 3
0064 1F pop ds
; get system sector translation table into data segment of program
0065 07 pop es ; recover extra seg value
0066 8B1E4A01 mov bx,xlt_offset ; get offset of trans table
006A 268B37 mov si,es:word ptr[bx] ; into SI
006D 85F6 test si,si ; if SI = 0 then system doesn't
006F 7514 0085 jnz has_table ; have a translation table
0071 BB4C01 mov bx,offset xlt_tab ; which means that I'll have
0074 8B0E3B01 mov cx,spt ; to init "xlt_tab" myself
0078 B000 mov al,0
initlop0:
007A 8807 mov byte ptr[bx],al
007C FEC0 inc al
007E 43 inc bx
007F E2F9 007A loop initlop0
0081 B001 mov al,1 ; set skew factor = 1
0083 EB15 009A jmps init_addr_tab
has_table:
0085 06 push es ; save extra seg again
0086 8B1E4A01 mov bx,xlt_offset ; get offset of trans table
008A BF4C01 mov di,offset xlt_tab ; DI = offset of program sector
; translation table
008D 8B0E3B01 mov cx,spt ; use sectors/track as
; counter value
0091 8E060900 mov es,data_base ; init ES value
0095 1F pop ds ; init DS
0096 F3A4 rep movsb
0098 06 push es ; restore old DS value
0099 1F pop ds
; make sure that serial numbers that cross sector boundries will be
; found
init_addr_tab:
009A 2BC0 sub ax,ax ; init address offset
009C BE4C01 mov si,offset xlt_tab ; SI -> xlt-tab
009F 8B0E3B01 mov cx,spt ; init counter
00A3 2AF6 sub dh,dh ; DH = 0
initlop9:
00A5 BBCC01 mov bx,offset addr_tab
00A8 8A14 mov dl,byte ptr[si] ; get sector number
00AA 46 inc si ; move pointer
00AB 2A164C01 sub dl,xlt_tab ; subtract 1st sector number
00AF 02D2 add dl,dl ; multiply by 2
00B1 03DA add bx,dx ; BX -> correct table entry
00B3 8907 mov word ptr[bx],ax ; put address into table
00B5 058000 add ax,128 ; AX = AX+bytes/sectorz
00B8 E2EB 00A5 loop initlop9
; depending on the system, each physical sector on a diskette can
; be made up of a number of logical sectors (128 bytes long). the
; following code analyses the system sector translate table to
CP/M ASM86 1.1 SOURCE: SERIAL16.A86 PAGE 4
; determine the number of logical sectors in a physical sector.
00BA BB4C01 mov bx,offset xlt_tab ; BX -> xlt_tab
xltlop0:
00BD 8A07 mov al,byte ptr[bx] ; AL = table entry
00BF 43 inc bx ; BX -> next byte in table
00C0 FEC0 inc al
00C2 3A07 cmp al,byte ptr[bx] ; see if the two numbers are in
00C4 74F7 00BD je xltlop0 ; the right order
00C6 81EB4C01 sub bx,offset xlt_tab ; if they aren't then calculate
; how long the sequence was
00CA 891E3901 mov spb,bx ; and save the value
; calculate skew of system sector translation table
00CE 8A874C01 mov al,xlt_tab[bx] ; get byte at xlt_tab+spb
00D2 2A064C01 sub al,xlt_tab ; and subtract byte at xlt_tab
00D6 8B1E3901 mov bx,spb ; now divide by sectors/block
00DA 2AE4 sub ah,ah ; prepare of division
00DC F6F3 div bl
00DE A23801 mov skew,al
; tell operator about skew
skew_prompt:
00E1 50 push ax ; save system skew
00E2 E8AD04 0592 call clear ; clear screen
00E5 BA7D07 mov dx,offset msg21 ; send message
00E8 E8A204 058D call pmsg
00EB 5A pop dx ; recover skew
00EC 80CA30 or dl,030h ; make it ASCII
00EF B102 mov cl,c_write
00F1 CDE0 int ccpm
; ask operator if he/she would like to change the sector skew
00F3 BA1E06 mov dx,offset msg16
00F6 E89404 058D call pmsg
00F9 E8A404 05A0 call get_char ; get Y/N response
00FC 3C4E cmp al,'N' ; check for No
00FE 7445 0145 je dont_change
; ask for new skew factor
0100 BA5306 mov dx,offset msg17
0103 E88704 058D call pmsg
0106 E8B004 05B9 call get_1num
0109 A23801 mov skew,al
; make new sector translation table using skew factor supplied by
; operator
010C BE4C01 mov si,offset xlt_tab ; BX is pointer into xlt_tab
010F 8A1C mov bl,byte ptr[si] ; init beginning sector number
0111 8AFB mov bh,bl
0113 8A163B01 mov dl,sptbyte ; calculate sectors/track +
0117 02D3 add dl,bl ; first sector number
0119 8A0E3801 mov cl,skew ; init loop counter
011D 2AED sub ch,ch
xltlop1:
011F 51 push cx ; save loop counter
xltlop2:
0120 8B0E3901 mov cx,spb ; init sectors/block counter
CP/M ASM86 1.1 SOURCE: SERIAL16.A86 PAGE 5
0124 53 push bx ; save sector # registers
xltlop3:
0125 883C mov byte ptr[si],bh ; put sector number into table
0127 46 inc si ; increment pointer
0128 FEC7 inc bh ; increment sector number
012A E2F9 0125 loop xltlop3
012C A13901 mov ax,spb ; calculate new starting sector
012F 8A0E3801 mov cl,skew
0133 F6E1 mul cl
0135 5B pop bx ; recover sector # registers
0136 02F8 add bh,al ; add skew*spt to starting
; sector number
0138 3AFA cmp bh,dl ; compare new starting sector #
; to first sector # + spt
013A 72E4 0120 jb xltlop2
013C 021E3901 add bl,spbbyte ; add sectors/block to 1st
; starting sector number
0140 8AFB mov bh,bl ; init starting sector
; number of the next sector
; block
0142 59 pop cx ; recover loop counter
0143 E2DA 011F loop xltlop1
dont_change:
; ok, now calculate many how bytes there are on a track.
; bytes/track = sectors/track * logical sector size
0145 A13B01 mov ax,spt
0148 BB8000 mov bx,128
014B F7E3 mul bx
014D A31F01 mov bpt,ax ; save value
0150 B135 mov cl,mc_max ; find 64k or less of free
0152 BA2101 mov dx,offset mcb ; memory
0155 CDE0 int ccpm
; check the disk for blank tracks starting at last track. blank
; tracks won't be copied
0157 BA4708 mov dx,offset msg1 ; tell operator about search
015A E83004 058D call pmsg
015D FC cld ; set direction flag forward
015E BA5204 mov dx,offset msg7 ; send 'Reading' message
0161 E82904 058D call pmsg
0164 8B0ED102 mov cx,last_trk ; initialize track counter
scan_loop:
0168 51 push cx ; save track counter
0169 880E0101 mov track,cl ; get current track
016D 8AC1 mov al,cl ; make track number ascii
016F E8E203 0554 call make_ascii
0172 BA7204 mov dx,offset ascii_trk ; print it
0175 E81504 058D call pmsg
0178 C706CC020000 mov dma_addr,0 ; initialize dma offset
017E E8E302 0464 call seek ; seek to track
0181 E83902 03BD call read ; read a track
CP/M ASM86 1.1 SOURCE: SERIAL16.A86 PAGE 6
0184 B0E5 mov al,blank ; init AL with the character
; which is found in blank
; (empty) sectors
0186 8E062101 mov es,m_base ; init segment reg
018A BF0000 mov di,0 ; offset is set to zero
018D 8B0E1F01 mov cx,bpt ; how many bytes to scan
0191 F3AE repe scasb ; scan until ZF=1 or CX=0
0193 750F 01A4 jne data_found ; if ZF=1 then have found data
0195 E83304 05CB call erase_trk ; erase old track message
0198 59 pop cx ; otherwise scan another track
0199 E2CD 0168 loop scan_loop ; if CX<>0
; the diskette is blank if program flow reaches this point
019B BA2608 mov dx,offset error_msg0
019E E8EC03 058D call pmsg ; inform operator that the
01A1 E8DF03 0583 call abort ; source disk is blank and
; abort operation
data_found:
01A4 59 pop cx ; if data is found then save
01A5 890ED102 mov last_trk,cx ; the number of the non-blank
; track
; the information on the source disk will more than likely need to be
; paged into memory. the following code calculates how many pages
; or blocks will be needed.
01A9 A12301 mov ax,m_length ; calculate number of bytes
01AC BB1000 mov bx,16 ; available to be used for
01AF F7E3 mul bx ; a buffer area
01B1 8B1E1F01 mov bx,bpt
01B5 F7F3 div bx
01B7 8B0ED102 mov cx,last_trk ; CX will contain number of
01BB 2B0E4801 sub cx,off ; tracks to be copied
01BF 3BC1 cmp ax,cx ; if block1 track count<lst_trk
01C1 7C0C 01CF jl over0 ; then get block2 track count
01C3 890E2B01 mov B1_trk_cnt,cx ; last_trk, block_cnt=
01C7 C7062F010100 mov block_cnt,1 ; 1 and jump to new_disk
01CD EB13 01E2 jmps over07
over0:
01CF 48 dec ax
01D0 A32B01 mov B1_trk_cnt,ax
01D3 2BD2 sub dx,dx
01D5 8BD8 mov bx,ax ; bx holds divisor
01D7 8BC1 mov ax,cx ; hold dividend in division
; operation
01D9 F7F3 div bx ; do division
01DB A32F01 mov block_cnt,ax ; move result to memory
01DE 89162D01 mov B2_trk_cnt,dx ; remainder = block2 track
; count
over07:
; prompt operator for number of serial fields on source disk
01E2 E8BD02 04A2 call get_cnt
01E5 3C00 cmp al,0 ; if count = 0 then don't ask
CP/M ASM86 1.1 SOURCE: SERIAL16.A86 PAGE 7
01E7 7403 01EC jz over09 ; for a starting serial number
; prompt operator for starting serial number
01E9 E88F02 047B call get_serial
over09:
; ask operator if he/she wants to verify the copy against the source
; disk and if so, how often
01EC E8A303 0592 call clear ; clear monitor screen
01EF BA7106 mov dx,offset msg18 ; ask question
01F2 E89803 058D call pmsg
01F5 C606270100 mov ver_freq,0 ; init verification frequency
; value
01FA E8A303 05A0 call get_char ; get yes/no answer
01FD 3C4E cmp al,'N' ; check for no
01FF 740C 020D je over01 ; if no then dont verify
; ask operator for frequency of verification
0201 BAA606 mov dx,offset msg19 ; send message
0204 E88603 058D call pmsg
0207 E8A502 04AF call get_2num ; get response from operator
020A A22701 mov ver_freq,al ; save value
over01:
; clear monitor screen
020D E88203 0592 call clear
0210 C606290100 mov dsk_cnt,0 ; init diskette counter
; this portion of code does the copying and serializing
new_disk:
0215 FC cld ; move current serial number
0216 8E060900 mov es,data_base ; into insert serial message
021A B90600 mov cx,length ser_def
021D BEA508 mov si,offset serial_number
0220 BF5005 mov di,offset serial_1
0223 F3A4 rep movsb
0225 BA4605 mov dx,offset msg3 ; prompt operator for
0228 E84803 0573 call pmsg_wait ; destination diskette
; home both disk drives
022B E84402 0472 call selectD
022E E81002 0441 call home
0231 E83802 046C call selectS
0234 E80A02 0441 call home
0237 A14801 mov ax,off ; don't copy reserved tracks
023A A2CE02 mov trackS,al
023D A2CF02 mov trackD,al
0240 A12B01 mov ax,B1_trk_cnt ; init track counter
0243 A33101 mov track_cnt,ax
CP/M ASM86 1.1 SOURCE: SERIAL16.A86 PAGE 8
0246 C606330100 mov tog0,0 ; decides whether to use
; B1_trk_cnt or B2_trk_cnt
024B C606340100 mov serial_cnt,0 ; used to check if all the
; serial fields were found
0250 BA5204 mov dx,offset msg7 ; send 'Reading' message
0253 E83703 058D call pmsg
0256 E8EF01 0448 call seekS ; read in a track so that
0259 C706CC020000 mov dma_addr,0 ; there is always an extra
025F E85B01 03BD call read ; one in memory
0262 E85F03 05C4 call erase_msg ; erase "Reading" message
0265 8B0E2F01 mov cx,block_cnt ; init block counter
create_dsk:
0269 51 push cx ; save block counter
026A 8B0E1F01 mov cx,bpt ; intialize dma offset
026E 890ECC02 mov dma_addr,cx
0272 E8F701 046C call selectS ; select source disk
0275 BA5204 mov dx,offset msg7 ; send 'Reading' message
0278 E81203 058D call pmsg
027B 8B0E3101 mov cx,track_cnt ; init track counter
lop0:
027F 51 push cx ; save track counter
0280 E8C501 0448 call seekS ; seek track on source drive
0283 E83701 03BD call read ; read a track
0286 E84203 05CB call erase_trk ; erase old track message
0289 59 pop cx ; recover track counter
028A E2F3 027F loop lop0
028C E83503 05C4 call erase_msg ; erase "Reading" message
028F E86002 04F2 call serialize ; insert current serial number
; into all serial fields in
; this block
0292 C706CC020000 mov dma_addr,0 ; same as above but write to
; destination drive
0298 E8D701 0472 call selectD ; select destination drive
029B BA6204 mov dx,offset msg8 ; send "Writing" message to
029E E8EC02 058D call pmsg ; console
02A1 8B0E3101 mov cx,track_cnt
lop1:
02A5 51 push cx
02A6 E8A801 0451 call seekD
02A9 E81801 03C4 call write
02AC E81C03 05CB call erase_trk ; erase old track message
02AF 59 pop cx
02B0 E2F3 02A5 loop lop1
02B2 E80F03 05C4 call erase_msg ; erase "Writing" message
; move extra track (read and searched but not written) from end of
CP/M ASM86 1.1 SOURCE: SERIAL16.A86 PAGE 9
; buffer to the beginning of the buffer
02B5 FC cld ; clear direction flag
02B6 8B0E1F01 mov cx,bpt ; init counter
02BA 8BC1 mov ax,cx ; calculate starting address
02BC 8B1E2B01 mov bx,B1_trk_cnt ; of data to be moved
02C0 F7E3 mul bx
02C2 8BF0 mov si,ax
02C4 BF0000 mov di,0 ; where block is to be moved
02C7 A12101 mov ax,m_base ; init segment registers
02CA 1E push ds ; save old values
02CB 06 push es
02CC 8ED8 mov ds,ax ; move in new values
02CE 8EC0 mov es,ax
02D0 F3A4 rep movsb ; do the move
02D2 07 pop es ; recover values of segment
02D3 1F pop ds ; registers
02D4 59 pop cx ; recover block counter
02D5 E292 0269 loop create_dsk ; do again if not last block
02D7 803E330101 cmp tog0,1 ; check if we have reached this
; point before
02DC 7416 02F4 je done ; if yes then we are done
02DE C606330101 mov tog0,1 ; no, so toggle tog0
02E3 A12D01 mov ax,B2_trk_cnt ; if B2_trk_cnt=0
02E6 3D0000 cmp ax,0 ; then we are done
02E9 7409 02F4 je done
02EB A33101 mov track_cnt,ax ; else do above again but with
02EE B90100 mov cx,1 ; B2_trk_cnt = track count
02F1 E975FF 0269 jmp create_dsk
done:
02F4 BA6204 mov dx,offset msg8 ; send "Writing" message
02F7 E89302 058D call pmsg ; to console
02FA E85401 0451 call seekD ; write last track to dest
02FD E8C400 03C4 call write ; drive
0300 A03501 mov al,count_num ; check if all serial fields
0303 3A063401 cmp al,serial_cnt ; were found
0307 7409 0312 je serial_ok ; if not then there is an error
0309 BA9C07 mov dx,offset error_msg3 ; inform operator of error
030C E87E02 058D call pmsg
030F E87102 0583 call abort ; abort operation
serial_ok:
0312 E8AF02 05C4 call erase_msg ; erase "Writing" message
0315 FE062901 inc dsk_cnt ; increment diskette counter
0319 A12901 mov ax,dsk_cntword ; get number of diskettes done
031C 8B0E2701 mov cx,ver_freqword ; get verification frequency
0320 E37C 039E jcxz dont_verify ; don't verify if CX = 0
0322 F6F1 div cl ; see if it's time to verify
0324 84E4 test ah,ah ; if DX = 0 then it's time
CP/M ASM86 1.1 SOURCE: SERIAL16.A86 PAGE 10
0326 7576 039E jnz dont_verify
; do the verification
0328 BA6C07 mov dx,offset msg20 ; send "Verifying" message
032B E85F02 058D call pmsg
032E 8B0ED102 mov cx,last_trk ; calculate number of tracks to
0332 A14801 mov ax,off ; compare
0335 2BC8 sub cx,ax
0337 41 inc cx ; correct result
0338 A2CE02 mov trackS,al
033B A2CF02 mov trackD,al
verlop0:
033E 51 push cx ; save track counter
033F E83001 0472 call selectD ; select dest disk
0342 E80C01 0451 call seekD ; seek to track on dest disk
0345 C706CC020000 mov dma_addr,0 ; init offset of 1st buffer
034B E86F00 03BD call read ; read a track from source disk
034E E87A02 05CB call erase_trk ; erase old track message
0351 E81801 046C call selectS ; select source drive
0354 E8F100 0448 call seekS ; seek to current track
0357 8B0E1F01 mov cx,bpt ; init 2nd buffer offset
035B 51 push cx ; temp save
035C 890ECC02 mov dma_addr,cx
0360 E85A00 03BD call read ; read a track from dest disk
0363 E86502 05CB call erase_trk ; erase old track message
0366 59 pop cx ; recover track data length
; into byte counter
0367 2BF6 sub si,si ; init 1st pointer
0369 8BF9 mov di,cx ; init 2nd pointer
verlop1:
036B 1E push ds ; save value of data seg reg
036C A12101 mov ax,m_base ; get extra seg reg value
036F 8EC0 mov es,ax ; init ES
0371 8ED8 mov ds,ax ; init DS
0373 F3A6 repe cmpsb ; verify
0375 1F pop ds ; recover data seg reg value
0376 7423 039B je verlop2 ; if ZF = 0 then verification
; failed. inform operator
0378 4F dec di ; correct 2nd buffer pointer
0379 56 push si ; save pointer to 1st buffer
037A 51 push cx ; save byte pointer
037B BED302 mov si,offset ser_def ; SI -> to ser_def
037E B90600 mov cx,length ser_def ; init counter
0381 F3A6 repe cmpsb ; do compare
0383 750A 038F jne verlop3
0385 59 pop cx ; recover byte counter
0386 83E905 sub cx,length ser_def-1 ; correct it
0389 5E pop si ; recover 1st buffer pointer
038A 83C605 add si,length ser_def-1 ; correct it
038D EBDC 036B jmps verlop1
; verification failed so inform operator to try it again
verlop3:
038F E80002 0592 call clear
CP/M ASM86 1.1 SOURCE: SERIAL16.A86 PAGE 11
0392 BAF207 mov dx,offset error_msg7
0395 E8F501 058D call pmsg
0398 E97AFE 0215 jmp new_disk
verlop2:
039B 59 pop cx ; recover track counter
039C E2A0 033E loop verlop0
dont_verify:
039E E8F101 0592 call clear ; clear monitor screen
03A1 FC cld ; insert current serial number
03A2 B90600 mov cx,length ser_def ; into remove message
03A5 8E060900 mov es,data_base
03A9 BEA508 mov si,offset serial_number
03AC BF9C05 mov di,offset serial_2
03AF F3A4 rep movsb
03B1 BA9105 mov dx,offset msg4 ; prompt operator to remove
03B4 E8D601 058D call pmsg ; copy
03B7 E87201 052C call inc_serial ; increment current serial
; number
03BA E958FE 0215 jmp new_disk ; do another disk
; read a track from the selected disk
read:
03BD C6061A010D mov io_tab,read_code
03C2 EB07 03CB jmps track_io
; write a track to the selected disk drive
write:
03C4 C6061A010E mov io_tab,write_code
03C9 EB00 03CB jmps track_io
; do track input or output on selected disk drive
track_io:
03CB B90400 mov cx,4 ; initialize io retry counter
io_retry:
03CE 51 push cx ; save retry counter
03CF E83E00 0410 call track_setup ; init dma base address
03D2 C606190100 mov sector,0 ; start with sector #0
03D7 8B0E3B01 mov cx,spt ; init sector counter
io_lop:
03DB 51 push cx ; save sector counter
03DC E83F00 041E call sectran ; perform sector translation
03DF BA1401 mov dx,offset set_sector ; set sector thru ccpm
03E2 B132 mov cl,s_bios
03E4 CDE0 int ccpm
03E6 BA0F01 mov dx,offset set_dma_offset ; set dma offset thru ccpm
03E9 B132 mov cl,s_bios
CP/M ASM86 1.1 SOURCE: SERIAL16.A86 PAGE 12
03EB CDE0 int ccpm
03ED B132 mov cl,s_bios ; set read/write func thru ccpm
03EF BA1A01 mov dx,offset io_tab
03F2 CDE0 int ccpm
03F4 84C0 test al,al ; io error if not zero
03F6 7510 0408 jnz io_error ; tell operator about io error
03F8 FE061901 inc sector ; next sector to read
03FC 59 pop cx ; recover sector counter
03FD E2DC 03DB loop io_lop
03FF 59 pop cx ; clean up stack
0400 A11F01 mov ax,bpt ; init dma_addr for next
0403 0106CC02 add dma_addr,ax ; track
0407 C3 ret
io_error:
0408 59 pop cx ; clean up stack
0409 E83500 0441 call home ; home disk
040C 59 pop cx ; recover retry counter
040D E2BF 03CE loop io_retry
040F C3 ret
track_setup:
0410 A12101 mov ax,m_base ; initialize dma base address
0413 A30B01 mov dma_base,ax
0416 B132 mov cl,s_bios
0418 BA0A01 mov dx,offset set_dma_base
041B CDE0 int ccpm
041D C3 ret
; do logical to physical sector translation
sectran:
041E 2AE4 sub ah,ah
0420 A01901 mov al,sector
0423 BB4C01 mov bx,offset xlt_tab
0426 D7 xlat xlt_tab
0427 A21501 mov tsector,al
042A 2AE4 sub ah,ah
042C 2A064C01 sub al,xlt_tab
0430 02C0 add al,al
0432 BBCC01 mov bx,offset addr_tab
0435 03D8 add bx,ax
0437 8B07 mov ax,word ptr[bx]
0439 0306CC02 add ax,dma_addr
043D A31001 mov dma_offset,ax
0440 C3 ret
; home the selected drive
home:
0441 C606010100 mov track,0
0446 EB1C 0464 jmps seek
CP/M ASM86 1.1 SOURCE: SERIAL16.A86 PAGE 13
; seek to the selected track on the source drive
seekS:
0448 A0CE02 mov al,trackS
044B FE06CE02 inc trackS
044F EB07 0458 jmps display_trk
; seek to the selected track on the destination drive
seekD:
0451 A0CF02 mov al,trackD
0454 FE06CF02 inc trackD
display_trk:
0458 A20101 mov track,al
045B E8F600 0554 call make_ascii ; make track # ascii
045E BA7204 mov dx,offset ascii_trk ; send track number to
0461 E82901 058D call pmsg ; console
; seek to the selected track on the selected drive
; "track" = desired track #
seek:
0464 B132 mov cl,s_bios
0466 BA0001 mov dx,offset seek_trk_tab
0469 CDE0 int ccpm
046B C3 ret
; select source disk
selectS:
046C 8A163601 mov dl,dskS
0470 EB04 0476 jmps select
; select destination disk
selectD:
0472 8A163701 mov dl,dskD
; select a disk drive for future operations
select:
0476 B10E mov cl,drv_set
0478 CDE0 int ccpm
047A C3 ret
; get starting serial number from operator
get_serial:
047B BAFC03 mov dx,offset msg2 ; send prompt message
047E E80C01 058D call pmsg ; to console
0481 BAA308 mov dx,offset con_buf0 ; point to console input buffer
0484 B10A mov cl,10 ; CP/M read console buffer
0486 CDE0 int ccpm
0488 803EA40806 cmp buf0_len,length ser_def ; check for correct number
; of digits
048D 7501 0490 jne bad_serial
048F C3 ret
CP/M ASM86 1.1 SOURCE: SERIAL16.A86 PAGE 14
bad_serial:
0490 C606A70406 mov error_msg2,length ser_def
0495 800EA70430 or error_msg2,030h ; make it ASCII
049A BA8E04 mov dx,offset error_msg1
049D E8ED00 058D call pmsg
04A0 EBD9 047B jmps get_serial
; get from the operator how many serial fields are on the source
; diskette. this is a safeguard to help prevent the wrong disk
; from being used.
get_cnt:
04A2 BA1E04 mov dx,offset msg6 ; send prompt message
04A5 E8E500 058D call pmsg ; to console
04A8 E80400 04AF call get_2num ; get a number (0-99)
; from operator
04AB A23501 mov count_num,al ; save number
04AE C3 ret
; input two ASCII numbers into buffer 1 and translate them into a
; binary number which is returned in the AL register
get_2num:
04AF BAAE08 mov dx,offset con_buf1 ; get address of buffer
04B2 B10A mov cl,10
04B4 CDE0 int ccpm
04B6 803EAF0802 cmp buf1_len,2 ; can't have more than
04BB 7609 04C6 jbe input_ok0 ; two digits 0-99
input_err0:
04BD BAD107 mov dx,offset error_msg6 ; tell operator about
04C0 E8CA00 058D call pmsg ; error and try again
04C3 E9E9FF 04AF jmp get_2num
input_ok0:
04C6 803EAF0800 cmp buf1_len,0 ; need at least one
04CB 74F0 04BD je input_err0 ; digit. tell operator
; if there isn't
04CD BBB008 mov bx,offset input_num ; bx -> input buffer
04D0 8A0EAF08 mov cl,buf1_len ; (cl) = digit count
04D4 2AED sub ch,ch ; zero upper half of cx
04D6 03D9 add bx,cx ; make bx point to
04D8 4B dec bx ; units digit of input
04D9 8A37 mov dh,byte ptr[bx] ; get units digit
04DB 80E60F and dh,00Fh ; mask off upper nybble
04DE E203 04E3 loop tens ; if (cx) <> 2 then get
; tens digit
04E0 E90C00 04EF jmp got_it ; only had one digit
tens:
04E3 4B dec bx ; make bx -> to tens
; digit
04E4 8A17 mov dl,byte ptr[bx] ; get tens digit
04E6 80E20F and dl,00Fh ; mask off upper nybble
04E9 B00A mov al,10 ; load multiplier
04EB F6E2 mul dl ; do multiply
CP/M ASM86 1.1 SOURCE: SERIAL16.A86 PAGE 15
04ED 02F0 add dh,al ; add tens to units
got_it:
04EF 8AC6 mov al,dh ; save number
04F1 C3 ret
serialize: ; locate all occurrances of serial numbers in buffer
04F2 FC cld ; set direction forward
04F3 8E062101 mov es,m_base ; point ES: to beginning of buffer
04F7 BF0000 mov di,0
04FA A11F01 mov ax,bpt
04FD 8B1E3101 mov bx,track_cnt
0501 43 inc bx ; remember that an extra track was read
0502 F7E3 mul bx
0504 8BC8 mov cx,ax
next_serial:
0506 BED302 mov si,offset ser_def ; point at pattern
0509 AC lodsb ; get first char of pattern into AL
050A F2AE repne scasb ; look for next occurance of AL
050C 751D 052B jne no_match ; if not match, then we are done
050E 57 push di ; save scan pointer
050F 51 push cx ; save count
0510 B90500 mov cx,(length ser_def)-1 ; residual length of pattern
0513 F3A6 repe cmpsb
0515 59 pop cx ; recover scan count
0516 5F pop di ; recover scan pointer
0517 75ED 0506 jne next_serial ; no, rest didn't match
0519 51 push cx ; save scan pointer
051A 4F dec di ; move di back to start of field
051B BEA508 mov si,offset serial_number ; si points to current serial
; number
051E B90600 mov cx,length ser_def ; counter for number of bytes to move
0521 F3A4 rep movsb
0523 59 pop cx ; recover scan pointer
0524 FE063401 inc serial_cnt
0528 E9DBFF 0506 jmp next_serial
no_match:
052B C3 ret
; increment the ASCII serial number
inc_serial:
052C B90600 mov cx,length ser_def ; length of serial number
052F BBA508 mov bx,offset serial_number ; bx points to start of string
0532 83C305 add bx,(length ser_def)-1 ; bx now points to end of string
addlop:
0535 51 push cx ; save length of pointer
0536 8A07 mov al,byte ptr[bx] ; get byte of serial number
CP/M ASM86 1.1 SOURCE: SERIAL16.A86 PAGE 16
0538 FEC0 inc al ; add 1 to it
053A 27 daa ; decimal adjust it
053B 9F lahf ; check to see if there was a
053C 80E410 and ah,10h ; carry from the lower half of
053F B104 mov cl,4 ; the al register
0541 D2E4 shl ah,cl
0543 7204 0549 jc fix ; if yes then increment the next
; byte of the serial number
0545 8807 mov byte ptr[bx],al ; else save byte and stop
0547 59 pop cx ; clean up stack
0548 C3 ret
fix:
0549 240F and al,0fh ; make high nybble of byte
054B 0C30 or al,30h ; equal to "3" again
054D 8807 mov byte ptr[bx],al ; save byte back in serial
; number
054F 4B dec bx ; point at next higher byte
0550 59 pop cx ; recover length of serial
; number
0551 E2E2 0535 loop addlop ; do again if CX<>0
0553 C3 ret
; translate the 8 bit digit in AL to ASCII into "ascii_trk"
make_ascii:
0554 BA2020 mov dx,' ' ; fill "ascii_trk" with blanks
0557 89167204 mov ascii_trk,dx
055B 89167404 mov ascii_trk+2,dx
055F BB7504 mov bx,offset ascii_trk+3 ; BX -> "ascii_trk"+3
0562 B20A mov dl,10 ; init divisor
makelop1:
0564 2AE4 sub ah,ah ; make AH zero
0566 F6F2 div dl ; and divide by 10
0568 80C430 add ah,'0' ; make remainder ascii
056B 8827 mov byte ptr[bx],ah ; store it in "ascii_trk"
056D 4B dec bx ; move pointer to next location
056E 84C0 test al,al ; see if quotient zero yet
0570 75F2 0564 jnz makelop1 ; no, got more digits
0572 C3 ret
; print the message at [DX] and wait for RETURN key
pmsg_wait:
0573 E81700 058D call pmsg ; print the message
wait_1:
0576 B101 mov cl,c_read ; CP/M Console Input
0578 CDE0 int ccpm
057A 3C03 cmp al,'C'-'@' ; see if control-C
057C 7405 0583 je abort ; terminate program
057E 3C0D cmp al,cr ; see if ASCII carriage return
0580 75F4 0576 jne wait_1 ; no, try again
0582 C3 ret ; back to caller
; abort the program
CP/M ASM86 1.1 SOURCE: SERIAL16.A86 PAGE 17
abort:
0583 BABD05 mov dx,offset abort_msg
0586 E8EAFF 0573 call pmsg_wait
0589 B100 mov cl,0 ; CP/M reboot function
058B CDE0 int ccpm
; print the string whose offset is in dx and is terminated by '$'
pmsg:
058D B109 mov cl,c_writebuf
058F CDE0 int ccpm
0591 C3 ret
; clears the monitor screen
clear:
0592 803ED002FF cmp clear_on,false ; see if clear screen enable is
0597 7406 059F je no_clear ; off
0599 BA6708 mov dx,offset clear_msg
059C E8EEFF 058D call pmsg
no_clear:
059F C3 ret
; get ASCII input from operator and translate to upper case
get_char:
05A0 B101 mov cl,c_read ; request single character
05A2 CDE0 int ccpm ; from console
05A4 3C03 cmp al,'C'-'@' ; check for control-C
05A6 74DB 0583 je abort ; abort operation if yes
05A8 245F and al,05Fh ; xlate lower to upper chase
; echo choice back to operator
echo_choice:
05AA 50 push ax ; temp save
05AB B208 mov dl,bs ; write over last input
05AD B102 mov cl,c_write
05AF CDE0 int ccpm
05B1 5A pop dx ; get temp save
05B2 52 push dx
05B3 B102 mov cl,c_write ; write it out
05B5 CDE0 int ccpm
05B7 58 pop ax
05B8 C3 ret
; get a single ASCII number from operator and check for .
get_1num:
05B9 B101 mov cl,c_read
05BB CDE0 int ccpm
05BD 3C03 cmp al,'C'-'@' ; check for control-C
05BF 74C2 0583 je abort
05C1 240F and al,00Fh
05C3 C3 ret
; this code erases the "Reading" and "Writing" messages from the
; monitor screen
CP/M ASM86 1.1 SOURCE: SERIAL16.A86 PAGE 18
erase_msg:
05C4 BA7804 mov dx,offset msg10
05C7 E8C3FF 058D call pmsg
05CA C3 ret
; this code erases the old track numbers from the monitor screen
erase_trk:
05CB BA8804 mov dx,offset msg11
05CE E8BCFF 058D call pmsg
05D1 C3 ret
dseg
org 0000h
; Page Zero Definitions
0000 code_length rw 1 ; low 16 bits code segment length
0002 code_length_h rb 1 ; high 8 bits code segment length
0003 code_base rw 1 ; base paragraph of code segment
0005 model_8080 rb 1 ; 8080 model byte
0006 data_length rw 1 ; low 16 bits data segment length
0008 data_length_h rb 1 ; high 8 bits data segment length
0009 data_base rw 1 ; base paragraph of data segment
000B rs 1 ; << reserved >>
000C extra_length rw 1 ; low 16 bits extra segment length
000E extra_length_h rb 1 ; high 8 bits extra segment length
000F extra_base rw 1 ; base paragraph of extra segment
org 0100h
0100 0A seek_trk_tab db 10 ; seek track function table
0101 track rb 4
0105 09 sel_dsk_tab db 9 ; select disk drive
0106 disk rb 4
010A 11 set_dma_base db 17 ; set dma base address function table
010B dma_base rw 2
010F 0C set_dma_offset db 12 ; set dma offset address function table
0110 dma_offset rw 2
0114 0B set_sector db 11 ; set sector function table
0115 tsector rb 4 ; holds translated sector #
0119 sector rb 1 ; holds untranslated sector #
011A io_tab rb 1 ; select read/write function table
011B rw 2
011F bpt rw 1 ; how many bytes per track
CP/M ASM86 1.1 SOURCE: SERIAL16.A86 PAGE 19
0121 mcb rw 0 ; memory control block
0121 m_base rw 1 ; base address (segment address)
0123 FF0F m_length dw 0FFFh ; desired length of memory area
0125 m_ext rw 1
0127 ver_freqword rw 0
0127 0000 ver_freq db 0,0 ; holds verification frequency value
0129 dsk_cntword rw 0
0129 0000 dsk_cnt db 0,0 ; number of copies made so far
012B B1_trk_cnt rw 1
012D B2_trk_cnt rw 1
012F block_cnt rw 1
0131 track_cnt rw 1
0133 tog0 rb 1
0134 serial_cnt rb 1
0135 count_num rs 1 ; holds number of serial fields
; to expect on source disk
0136 00 dskS db 0
0137 01 dskD db 1
0138 skew rb 1 ; reserve storage for skew factor
0139 spb rw 0 ; sectors/block
0139 spbbyte rb 2
013B DPB rb 0 ; Disk Parameter Block
013B spt rw 0 ; sector per track
013B sptbyte rb 2
013D bsh rb 1 ; block shift factor
013E blm rb 1 ; block mask
013F exm rb 1 ; extent mask
0140 dsm rw 1 ; total storage capacity of drive
0142 drm rw 1 ; number of directory entries
0144 al0 rb 1
0145 al1 rb 1
0146 cks rw 1
0148 off rw 1 ; number of reserved tracks
014A xlt_offset rw 1 ; offset of system translate table
014C xlt_tab rb 128 ; will contain sector translation table
01CC addr_tab rw 128 ; will contain sector address offsets
; from beginning of track address in
; disk data buffer
02CC dma_addr rw 1 ; will hold dma offset by track
02CE trackS rb 1
CP/M ASM86 1.1 SOURCE: SERIAL16.A86 PAGE 20
02CF trackD rb 1
02D0 00 clear_on db true
02D1 4C00 last_trk dw 76
02D3 363534333231 ser_def db '654321'
02D9 0D0A0A msg0 db cr,lf,lf
02DC 2D2D2D2D2D2D db '-------------------------'
2D2D2D2D2D2D
2D2D2D2D2D2D
2D2D2D2D2D2D
2D
02F5 2D2D2D2D2D2D db '-------------------------'
2D2D2D2D2D2D
2D2D2D2D2D2D
2D2D2D2D2D2D
2D
030E 2D db '-'
030F 0D0A db cr,lf
0311 53455249414C db 'SERIAL16 V1.0 Serial No. '
313620202020
202020202020
56312E302020
53657269616C
204E6F2E20
0334 585858582D30 db 'XXXX-0000-999999'
3030302D3939
39393939
0344 0D0A db cr,lf
0346 436F70797269 db 'Copyright (C) 1982'
676874202843
292031393832
0358 0D0A db cr,lf
035A 446967697461 db 'Digital Research, Inc. '
6C2052657365
617263682C20
496E632E2020
202020202020
2020
037A 416C6C205269 db 'All Rights Reserved'
676874732052
657365727665
64
038D 0D0A db cr,lf
038F 2D2D2D2D2D2D db '-------------------------'
2D2D2D2D2D2D
2D2D2D2D2D2D
2D2D2D2D2D2D
2D
03A8 2D2D2D2D2D2D db '-------------------------'
CP/M ASM86 1.1 SOURCE: SERIAL16.A86 PAGE 21
2D2D2D2D2D2D
2D2D2D2D2D2D
2D2D2D2D2D2D
2D
03C1 2D db '-'
03C2 0D0A0A db cr,lf,lf
03C5 4469736B6574 db 'Diskette Generation Utility',cr,lf
74652047656E
65726174696F
6E205574696C
6974790D0A
03E2 666F72204350 db 'for CP/M-86 based systems'
2F4D2D383620
626173656420
73797374656D
73
03FB 24 db '$'
03FC 0D0A0A msg2 db cr,lf,lf
03FF 456E74657220 db 'Enter starting serial number '
737461727469
6E6720736572
69616C206E75
6D6265722020
041D 24 db '$'
041E 070D0A0A msg6 db bell,cr,lf,lf
0422 456E74657220 db 'Enter number of serial fields on source disk'
6E756D626572
206F66207365
7269616C2066
69656C647320
6F6E20736F75
726365206469
736B
044E 203F20 db ' ? '
0451 24 db '$'
0452 52656164696E msg7 db 'Reading Track '
672054726163
6B2020
0461 24 db '$'
0462 57726974696E msg8 db 'Writing Track '
672054726163
6B2020
0471 24 db '$'
0472 msg9 rs 0
0472 ascii_trk rw 2
0476 20 db ' '
0477 24 db '$'
CP/M ASM86 1.1 SOURCE: SERIAL16.A86 PAGE 22
0478 080808080808 msg10 db bs,bs,bs,bs,bs,bs,bs,bs,bs,bs
08080808
0482 080808080808 db bs,bs,bs,bs,bs,bs
0488 0808080808 msg11 db bs,bs,bs,bs,bs
048D 24 db '$'
048E 0D0A0A error_msg1 db cr,lf,lf
0491 53657269616C db 'Serial number must be '
206E756D6265
72206D757374
20626520
04A7 error_msg2 rb 1
04A8 206469676974 db ' digits long. Try again !!! '
73206C6F6E67
2E2054727920
616761696E20
2121212020
04C5 24 db '$'
04C6 0D0A0A0A msg12 db cr,lf,lf,lf
04CA 536F75726365 db 'Source Drive is (A,B,etc.) ? '
204472697665
206973202841
2C422C657463
2E29203F20
04E7 24 db '$'
04E8 0D0A0A msg13 db cr,lf,lf
04EB 44657374696E db 'Destination Drive is (A,B,etc.) ? '
6174696F6E20
447269766520
69732028412C
422C6574632E
29203F20
050D 24 db '$'
050E 0D0A0A msg14 db cr,lf,lf
0511 496E73657274 db 'Insert Source Disk '
20536F757263
65204469736B
20
0524 616E64207479 db 'and type "Return" to continue '
706520225265
7475726E2220
746F20636F6E
74696E756520
0542 0D0A0A db cr,lf,lf
0545 24 db '$'
0546 0D0A0A msg3 db cr,lf,lf
0549 496E73657274 db 'Insert '
CP/M ASM86 1.1 SOURCE: SERIAL16.A86 PAGE 23
20
0550 serial_1 rb length ser_def
0556 20696E746F20 db ' into destination drive'
64657374696E
6174696F6E20
6472697665
056D 0D0A db cr,lf
056F 7468656E2074 db 'then type "Return" to continue'
797065202252
657475726E22
20746F20636F
6E74696E7565
058D 0D0A0A db cr,lf,lf
0590 24 db '$'
0591 070D0A0A msg4 db bell,cr,lf,lf
0595 52656D6F7665 db 'Remove '
20
059C serial_2 rb length ser_def
05A2 2066726F6D20 db ' from destination drive'
64657374696E
6174696F6E20
6472697665
05B9 0D0A0A db cr,lf,lf
05BC 24 db '$'
05BD 0D0A0D0A abort_msg db cr,lf,cr,lf
05C1 0D0A2A2A2A20 db cr,lf,'*** Serialization terminated ***'
53657269616C
697A6174696F
6E207465726D
696E61746564
202A2A2A
05E3 0D0A db cr,lf
05E5 0D0A5265706C db cr,lf,'Replace disk in Drive A:'
616365206469
736B20696E20
447269766520
413A
05FF 0D0A09207468 db cr,lf,' then type ENTER to reboot ','$'
656E20747970
6520454E5445
5220746F2072
65626F6F7420
24
061E 0D0A0A msg16 db cr,lf,lf
0621 576F756C6420 db 'Would you like to change the skew factor'
796F75206C69
6B6520746F20
6368616E6765
207468652073
CP/M ASM86 1.1 SOURCE: SERIAL16.A86 PAGE 24
6B6577206661
63746F72
0649 2028592F4E29 db ' (Y/N) ? '
203F20
0652 24 db '$'
0653 0D0A0A msg17 db cr,lf,lf
0656 456E74657220 db 'Enter skew factor (1-9) ? '
736B65772066
6163746F7220
28312D392920
3F20
0670 24 db '$'
0671 0D0A0A msg18 db cr,lf,lf
0674 446F20796F75 db 'Do you want to perform copy verification'
2077616E7420
746F20706572
666F726D2063
6F7079207665
726966696361
74696F6E
069C 2028592F4E29 db ' (Y/N) ? '
203F20
06A5 24 db '$'
06A6 0D0A0A0A msg19 db cr,lf,lf,lf
06AA 31203D206576 db '1 = every disk is verified'
657279206469
736B20697320
766572696669
6564
06C4 0D0A db cr,lf
06C6 32203D206576 db '2 = every 2nd disk is verified'
65727920326E
64206469736B
206973207665
726966696564
06E4 0D0A db cr,lf
06E6 33203D206576 db '3 = every 3rd disk is verified'
657279203372
64206469736B
206973207665
726966696564
0704 0D0A220D0A22 db cr,lf,'"',cr,lf,'"',cr,lf,'"',cr,lf
0D0A220D0A
070F 3939203D2065 db '99 = every 99th disk is verified'
766572792039
397468206469
736B20697320
766572696669
6564
CP/M ASM86 1.1 SOURCE: SERIAL16.A86 PAGE 25
072F 0D0A0A db cr,lf,lf
0732 486F77206F66 db 'How often do you want the verification to'
74656E20646F
20796F752077
616E74207468
652076657269
666963617469
6F6E20746F
075B 206F63637572 db ' occur (1-99) ? '
2028312D3939
29203F20
076B 24 db '$'
076C 566572696679 msg20 db 'Verifying Track '
696E67205472
61636B20
077C 24 db '$'
077D 0D0A0A msg21 db cr,lf,lf
0780 546865206375 db 'The current sector skew is '
7272656E7420
736563746F72
20736B657720
697320
079B 24 db '$'
079C 070D0A0A error_msg3 db bell,cr,lf,lf
07A0 446964206E6F db 'Did not find all of the required serial '
742066696E64
20616C6C206F
662074686520
726571756972
656420736572
69616C20
07C8 6669656C6473 db 'fields'
07CE 0D0A db cr,lf
07D0 24 db '$'
07D1 0D0A0A error_msg6 db cr,lf,lf
07D4 57726F6E672E db 'Wrong. Need one or two digits'
204E65656420
6F6E65206F72
2074776F2064
6967697473
07F1 24 db '$'
07F2 070D0A0A error_msg7 db bell,cr,lf,lf
07F6 2A2A2A2A2056 db '**** Verification failed ****'
657269666963
6174696F6E20
6661696C6564
202A2A2A2A
CP/M ASM86 1.1 SOURCE: SERIAL16.A86 PAGE 26
0813 0D0A0A db cr,lf,lf
0816 547279206974 db 'Try it again.'
20616761696E
2E
0823 0D0A db cr,lf
0825 24 db '$'
0826 070D0A0A error_msg0 db bell,cr,lf,lf
082A 205468652053 db ' The Source Disk is BLANK '
6F7572636520
4469736B2069
7320424C414E
4B20
0844 0D0A db cr,lf
0846 24 db '$'
0847 0D0A0A msg1 db cr,lf,lf
084A 436865636B69 db 'Checking for blank tracks'
6E6720666F72
20626C616E6B
20747261636B
73
0863 0D0A0A db cr,lf,lf
0866 24 db '$'
0867 0D0A0A0A0A0A clear_msg db cr,lf,lf,lf,lf,lf,lf,lf,lf,lf,lf,lf,lf,lf,lf
0A0A0A0A0A0A
0A0A0A
0876 0A0A0A0A0A0A db lf,lf,lf,lf,lf,lf,lf,lf,lf,lf,lf,lf,lf,lf,lf
0A0A0A0A0A0A
0A0A0A
0885 0A0A0A0A0A db lf,lf,lf,lf,lf
088A 0B0B0B0B0B0B db vt,vt,vt,vt,vt,vt,vt,vt,vt,vt,vt,vt,vt,vt,vt
0B0B0B0B0B0B
0B0B0B
0899 0B0B0B0B0B0B db vt,vt,vt,vt,vt,vt,vt,vt,vt
0B0B0B
08A2 24 db '$'
08A3 0A con_buf0 db 10 ; buffer used to read
08A4 buf0_len rb 1 ; serial number
08A5 serial_number rb length ser_def
08AB rb 10-1-length ser_def
08AE 05 con_buf1 db 5 ; another console input buffer
08AF buf1_len rb 1
08B0 input_num rb 5
08B5 00 db 0 ; force out end of data segment
CP/M ASM86 1.1 SOURCE: SERIAL16.A86 PAGE 27
END OF ASSEMBLY. NUMBER OF ERRORS: 0. USE FACTOR: 6%