📄 fcbs.a86
字号:
test bx,bx ; did we have a partial read for
jnz fcb_block_rw20 ; a reason like EOF ?
mov bx,2 ; no, we must have truncated it
fcb_block_rw20:
ret
fcb_size:
;--------
call fcb_path_prep
mov ax,MS_X_CHMOD ; it's a get info
mov fcb_pb+6,0
call fcb_fdos
jc fcb_size40
call fcb_point ; ES:BX = FCB
mov cx,es:MSF_RECSIZE[bx] ; get the record size
test cx,cx ; is it non-zero ?
jnz fcb_size10 ; if not
mov cx,128 ; make it 128 bytes
fcb_size10:
mov ax,fcb_pb+10
mov dx,fcb_pb+12 ; DX:AX = file length in bytes
call div_32 ; DX:AX = file length in records
jcxz fcb_size20 ; was there an overflow
add ax,1
adc dx,0 ; include an extra record
fcb_size20:
call fcb_point ; ES:BX = FCB
mov es:MSF_RR[bx],ax ; low word of size
mov es:MSF_RR2[bx],dl ; hi byte of size
cmp es:MSF_RECSIZE[bx],64 ; if record size < 64 bytes
jae fcb_size30 ; then we use a 4 byte
mov es:MSF_RR2+1[bx],dh ; random record position
fcb_size30:
xor bx,bx ; good return
fcb_size40:
ret
; Utility FCB subroutines
;========================
fcb_handle_vfy:
;--------------
; Verify FCB is valid and open, do not return if it isn't
; nb. Called with nothing on stack
;
; On Entry:
; FCB address in parameter block
; On Exit:
; AX preserved
; ES:BX -> FCB (skipping EXT bit if present)
; fcb_pb+2 = IFN of handle
; On Error - blow away caller and return error in BX
;
; DEBUG - on reopen we could do more checks to ensure we are re-opening the
; same file
push ax
call fcb_point
cmp es:MSF_RECSIZE[bx],0
jne fcb_handle_vfy10
mov es:MSF_RECSIZE[bx],128
fcb_handle_vfy10:
mov al,es:MSF_IFN[bx] ; get IFN
call ifn2dhndl ; ES:BX -> DHNDL_
jc fcb_handle_vfy20 ; it must be a valid IFN
test es:DHNDL_MODE[bx],DHM_FCB
jz fcb_handle_vfy20 ; it must be an FCB..
cmp es:DHNDL_COUNT[bx],0
jne fcb_handle_vfy30 ; it must also be open..
fcb_handle_vfy20:
call fcb_point
push es:MSF_RECSIZE[bx] ; save current record size
push es:MSF_BLOCK[bx] ; save current block number
push es ! push bx
call fcb_open ; try to re-open the file
pop bx ! pop es ; point back at FCB
pop es:MSF_BLOCK[bx] ; restore current block number
pop es:MSF_RECSIZE[bx] ; restore record size
jc fcb_handle_err
mov al,es:MSF_IFN[bx] ; get new IFN
fcb_handle_vfy30:
xor ah,ah
mov fcb_pb+2,ax ; set parameter block accordingly
call fcb_point ; ES:BX -> MSF_
pop ax
clc
ret
fcb_handle_err:
add sp,2*WORD ; discard AX and near return address
cmp ax,ED_HANDLE ; if we have run out of handles then
jne fcb_handle_err10 ; say no FCB's, else return error
mov ax,ED_NOFCBS
fcb_handle_err10:
xchg ax,bx ; error code in BX
stc
ret
fcb_path2_prep:
;--------------
; On Entry:
; FCB address in parameter block
; On Exit:
; ES:BX -> FCB (skipping EXT bit if present)
; fcb_pb+6/8 -> unparse name from FCB
;
call fcb_point ; point at the FCB
mov al,es:MSF_DRIVE[bx] ; get drive
add bx,16 ; point at 2nd name in FCB
mov di,offset fcb_path2
mov fcb_pb+6,di
mov fcb_pb+8,ds ; point at buffer we want
jmps fcb_path_prep_common
fcb_path_prep:
;-------------
; On Entry:
; FCB address in parameter block
; On Exit:
; ES:BX -> FCB (skipping EXT bit if present)
; fcb_pb+2/4 -> unparse name from FCB
;
xor ax,ax ; assume no attribute
mov bx,2[bp] ; BX -> parameter block
les bx,2[bx] ; ES:BX -> FCB
cmp es:MSF_EXTFLG[bx],0ffh ; is it an extended FCB
jne fcb_path_prep10
or al,es:MSF_ATTRIB[bx] ; we can use file mode from XFCB
add bx,7 ; skip EXT bit of FCB
fcb_path_prep10:
mov fcb_pb+8,ax ; remember the attribute
mov al,es:MSF_DRIVE[bx] ; get drive
mov di,offset fcb_path
mov fcb_pb+2,di
mov fcb_pb+4,ds ; point at buffer we want
fcb_path_prep_common:
dec al ; 0 = default drive
jns fcb_path_prep20
mov al,current_dsk ; use default drive
fcb_path_prep20:
push ds
push ds ! push es
pop ds ! pop es ; ES:DI -> name buffer
add al,'A' ; make drive ASCII
stosb
mov al,':'
stosb ; now we have 'd:'
lea si,MSF_NAME[bx] ; DS:SI -> source name
movsw ! movsw
movsw ! movsw ; copy the name leaving spaces intact
mov al,'.'
stosb
movsw ! movsb ; copy the extention
pop ds
; jmps fcb_point ; point ES:BX at FCB again
fcb_point:
;---------
; On Entry:
; FCB address in parameter block
; On Exit:
; ES:BX -> FCB (skipping EXT bit if present)
; (All other regs preserved)
;
mov bx,2[bp] ; BX -> parameter block
les bx,2[bx] ; ES:BX -> FCB
cmp es:MSF_EXTFLG[bx],0ffh ; is it an extended FCB
jne fcb_point10
add bx,7 ; skip EXT bit of FCB
fcb_point10:
ret
fcb_get_count:
;-------------
; On Entry:
; none
; On Exit:
; AX = bytes per record
; CX = callers CX count
; All regs fair game
;
call fcb_point ; ES:BX -> FCB
mov si,2[bp] ; SI -> parameter block
mov cx,6[si] ; CX = count
mov ax,es:MSF_RECSIZE[bx] ; get record size
ret
fcb_update_seq:
;--------------
; On Entry:
; CX = byte count actually transferred
; On Exit:
; CX = record count transferred
; All other regs fair game
; CR/BLOCK updated with new value
;
mov ax,cx
xor dx,dx ; DX:AX = byte count transfered
call fcb_point ; ES:BX -> FCB
div es:MSF_RECSIZE[bx] ; make records xfered
push ax ; save records xfered
xchg ax,cx ; also in CX for later
mov ax,128
mul es:MSF_BLOCK[bx] ; DX:AX = record of block
add ax,cx
adc dx,0 ; add in amount just xfered
mov cl,es:MSF_CR[bx]
xor ch,ch ; now add in CR as a word
add ax,cx
adc dx,0 ; DX:AX = record
mov dh,dl ; DH:AX = record for common code
jmps fcb_update_common
fcb_update_rr:
;-------------
; On Entry:
; CX = byte count actually transferred
; On Exit:
; CX = record count transferred
; All other regs fair game
; Random Record and CR/BLOCK updated with new value
;
xchg ax,cx
xor dx,dx ; DX:AX = byte count transfered
call fcb_point ; ES:BX -> FCB
div es:MSF_RECSIZE[bx] ; make records xfered
push ax ; save records xfered
add es:MSF_RR[bx],ax ; update the RR field
adc es:MSF_RR2[bx],0 ; and the overflow
mov ax,es:MSF_RR[bx] ; get low part of RR
mov dh,es:MSF_RR2[bx] ; and the hi part
fcb_update_common:
mov dl,ah ; DX will be block number
shl al,1 ; get top bit of CR into CY
adc dx,dx ; then into DX
shr al,1 ; AL = CR (remember mod 128)
mov es:MSF_CR[bx],al ; set the CR field
mov es:MSF_BLOCK[bx],dx ; and the block field
pop cx ; recover records xfered
ret
fcb_seek_seq:
;------------
; Seek to position in file indicated by the RR position
; On Entry:
; ES:BX -> FCB_
; On Exit:
; CY clear if no problem, fcb_pb+2=IFN
; else
; CY set, AX = BX = error code
; All other regs fair game
;
call fcb_point ; ES:BX -> FCB_
mov ax,128
mul es:MSF_BLOCK[bx] ; get record in DX:AX
mov cl,es:MSF_CR[bx]
xor ch,ch
add ax,cx ; add in CR
adc dx,0 ; so DX:AX is really the record
push ax ; save low word of record
mov ax,dx
mul es:MSF_RECSIZE[bx] ; DX:AX = byte offset in file/10000h
mov cx,ax ; save the important word
pop ax ; recover low word of record
jmps fcb_seek_common
fcb_seek_rr:
;-----------
; Seek to position in file indicated by the RR position
; On Entry:
; ES:BX -> FCB_
; On Exit:
; CY clear if no problem, fcb_pb+2=IFN
; else
; CY set, AX = BX = error code
; All other regs fair game
;
call fcb_point ; ES:BX -> FCB_
mov al,es:MSF_RR2[bx]
xor ah,ah
mul es:MSF_RECSIZE[bx] ; DX:AX = byte offset in file/10000h
mov cx,ax ; save the important word
mov ax,es:MSF_RR[bx]
fcb_seek_common:
mul es:MSF_RECSIZE[bx] ; DX:AX = byte offset in file
add dx,cx ; add the two bits together
mov fcb_pb+4,ax
mov fcb_pb+6,dx ; save position
mov fcb_pb+8,0 ; seek from start
xor ax,ax
mov al,es:MSF_IFN[bx] ; AX = IFN
mov fcb_pb+2,ax ; save IFN
mov ax,MS_X_LSEEK
jmp fcb_fdos ; try and seek to this position
fcb_search:
;----------
; On Entry:
; AX = operation to perform
; On Exit:
; AX = 0, or ED_ error code (CY set if error)
push dma_offset
push dma_segment
mov dma_offset,offset fcb_search_buf
mov dma_segment,ds
call fcb_fdos ; do the search
pop dma_segment
pop dma_offset
test ax,ax ; was there an error
stc ; assume there was
js fcb_search10 ; return the error
xor ax,ax ; no problems
fcb_search10:
ret
fcb_save_search_state:
;---------------------
; On entry DS=PCMODE
call fcb_point
lea di,MSF_NAME[bx] ; ES:DI -> FCB name
mov si,offset fcb_search_buf
lodsb ; get 1st byte = drive info
mov cx,20/WORD ; copy 20 bytes to FCB
rep movsw ; (the rest of the search template)
stosb ; drive info byte follow them
les di,dword ptr dma_offset ; ES:DI -> search state in DMA address
mov si,2[bp] ; SI -> parameter block
lds si,2[si] ; DS:SI -> FCB_
cmp ds:MSF_EXTFLG[si],0ffh ; extended FCB ?
jne fcb_sss10
mov cx,7 ; copy extended FCB portions too
rep movsb ; we have copied up to name
fcb_sss10:
stosb ; save drive byte info
push di
mov al,' ' ; space fill name
mov cx,11
rep stosb ; all blanks now
pop di
push ss ! pop ds ; DS:SI -> pathname
mov si,offset fcb_search_buf+1Eh
push di ; unparse knowing name is good
mov cx,8 ; length of name field
fcb_sss20:
lodsb ; treat '.' and '..' specially
cmp al,'.' ; is either possible ?
jne fcb_sss30 ; no, continue as normal
stosb ; copy the '.'
loop fcb_sss20 ; go around for another '.'
jmps fcb_sss40 ; this name is rubbish!!
fcb_sss30:
dec si ; forget the non '.'
call parse_one ; parse just the name
fcb_sss40:
pop di
add di,8 ; di -> fcb ext field
cmp al,'.' ; do we have an extention ?
jne fcb_sss50
mov cx,3 ; length of ext field
push di
call parse_one ; parse just extension
pop di
fcb_sss50:
add di,3 ; di -> rest of fcb
mov si,offset fcb_search_buf+15h
movsb ; copy the attribute field
xor ax,ax
mov cx,10/WORD
rep stosw ; 10 bytes of zeros
movsw ; copy time
movsw ; copy date
mov ax,word ptr srch_buf+21+DBLOCK1
stosw ; 1st block
movsw ! movsw ; copy filesize
ret
fcb_restore_search_state:
;------------------------
; On entry DS=PCMODE
push ds
call fcb_point ; ES:BX -> FCB_
push es ! push ds
pop es ! pop ds ; swap DS/ES
mov di,offset fcb_search_buf+1
; ES:DI -> internal state
lea si,1[bx] ; DS:SI -> FCB+1
mov cx,10
rep movsw ; copy info from FCB
lodsb ; get "drive" info
mov es:fcb_search_buf,al ; it's the 1st byte in the srch state
pop ds
ret
fcb_fdos:
;--------
; Make an FDOS call (NB. We don't have MX here, so it's OK)
; Set top bit of remote_call flag so we use IFN's not XFN's
; On Entry:
; AX = FDOS operation
; fcb_pb -> FDOS parameter block
; On Exit:
; As FDOS call
;
mov fcb_pb,ax ; save operation type
or remote_call,DHM_FCB ; forget about PSP during FCB call
mov dx,offset fcb_pb ; DS:DX -> parameter block
push ds
push bp
call fdos_entry ; call the FDOS
pop bp
pop ds
and remote_call,not DHM_FCB ; FCB operation over
cmp ax,ED_LASTERROR
cmc ; CY set if an error occurred
ret
div_32:
; Entry: DX,AX = long dividend
; CX = word divisor
; Exit: DX,AX = long result
; CX = remainder
jcxz div0 ; divide by 0
cmp cx,1
je div1 ; divide by 1
push di
push bx
xor bx,bx ; BX = 0
xchg ax,bx ; low word in BX, AX = 0
xchg ax,dx ; high word in DX:AX
push ax ; save high word
div cx ; divide high part
mov di,ax ; save result
mul cx ; AX = even divisor part
pop dx ; old high in DX
sub dx,ax ; eliminate even part
xchg ax,bx ; AX = low word
div cx ; low part in AX
mov cx,dx ; CX = remainder
mov dx,di ; high result in DX
pop bx
pop di
ret
div0:
mov ax,-1
mov dx,ax
ret
div1:
dec cx ; CX = remainder = 0
ret
PCMODE_DATA DSEG WORD
extrn fcb_pb:word
extrn fcb_path:byte
extrn fcb_path2:byte
extrn fcb_search_buf:byte
extrn current_dsk:byte
extrn current_psp:word
extrn dma_offset:word
extrn dma_segment:word
extrn machine_id:word
extrn remote_call:word
extrn srch_buf:byte
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -