⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dirs.asm

📁 random.zip 随机数产生器的汇编源代码 cmdsrc.zip 一个文本编辑器的汇编源代码
💻 ASM
字号:
; DIRS.ASM
; (c) 1989, 1990 Ashok P. Nadkarni
;
;This module implements the directory stack feature of the cmdedit program.

	INCLUDE ascii.inc
	INCLUDE common.inc
	INCLUDE general.inc
	INCLUDE	buffers.inc
	INCLUDE dos.inc
	INCLUDE bios.inc

	PUBLIC	dirs_init
	PUBLIC	execute_popd
	PUBLIC	execute_pushd
	PUBLIC	execute_chd
	PUBLIC	execute_rstdir
	PUBLIC	enable_dircmds

PATHBUF_SIZE EQU 68

CSEG	SEGMENT	PARA PUBLIC 'CODE'

	EXTRN	user_command:BYTE
	EXTRN	in_appl:BYTE
	EXTRN	linebuf:BYTE		;line buffer
	EXTRN	lastchar:WORD
	EXTRN	dirstk_error:BYTE
	EXTRN	resident:BYTE
	EXTRN	abort_install:PROC
	EXTRN	abort_processing:PROC
	EXTRN	skip_whitespace:PROC
	EXTRN	skip_nonwhite:PROC
	EXTRN	tolower:PROC

dir_stk	$string_stack   <>		;Buffer descriptors
enable_dircmds	db	1		;If 1, enables directory commands
;					 even if caller is not DOS

DGROUP	GROUP	CSEG
	ASSUME	CS:DGROUP,DS:DGROUP,ES:DGROUP,SS:DGROUP


;+
; FUNCTION : dirs_init
;
; Initializes the various data structures associated with the
; directory stack buffer. CALLER MUST ENSURE PASSED ADDRESSES ARE VALID
; AND BUFFER IS LARGE ENOUGH.
;
; Parameters:
;	AX 	- length of buffer in bytes
;	BX	- address of buffer
;
; Returns:
;	AX =	0 if no errors
;		-1 otherwise
; Registers destroyed : BX
;-
dirs_init proc	near
	push	bx
	mov	bx,offset DGROUP:dir_stk ;bx := address of buffer descriptors
	xchg	ax,cx			;CX = buffer size
	pop	ax			;AX = Buffer address
					;BX points to appropriate descriptor
	call	near ptr strstk_init	;Initialize buffer and descriptor
	ret
dirs_init	endp


;+
; FUNCTION: execute_rstdir
;
;	Called to reset the directory stack.
;
; Parameters:
;	None.
;-
execute_rstdir proc near
	mov	bx,offset DGROUP:dir_stk
	call	near ptr strstk_reset
	ret
execute_rstdir endp

;+
; FUNCTION : dir_push
;
;	Called to push a drive and path onto the directory stack. The
;	string must end in a 0 byte.
;
; Parameters:
;	DX	->string to push
;
; Returns:
;	CF	= 1 if errors
;		  0 no errors
;
; Register(s) destroyed:
;	AX,BX,CX,DX
;-
dir_push proc	near
	@save	di
	mov	di,dx				;di->string
	mov	cx,0ffffh
	xor	al,al
	repne	scasb
	mov	ax,cx
	not	ax				;AX<-length of string
;						 including null terminator
	mov	bx,offset DGROUP:dir_stk
	xor	cx,cx				;Don't force push
	call	near ptr strstk_push		;Params AX,BX,CX,DX
	; strstk_push sets/resets CF
	@restore
	ret
dir_push endp

;+
; FUNCTION : abort_dir_op
;
;	Called to abort a directory stack operation. Action taken
;	depends on whether the program is already resident or is being
;	installed. This routine does NOT return to caller.
;
; Parameters:
;	AX	= code to pass to abort_processing
;
; Returns:
;	Nothing.
; Register(s) destroyed:
;-
abort_dir_op proc near
	mov	dx,offset DGROUP:abort_processing
	cmp	resident,0
	jne	@abort_dir_op_90		;Jump if resident
	@DispStr dirstk_error
	mov	dx,offset DGROUP:abort_install
@abort_dir_op_90:
	jmp	dx
abort_dir_op endp




;+
; FUNCTION : check_dircmd_allowed
;
;	Makes sure DOS is the caller or directory commands have been
;	enabled for all applications and returns. Else aborts.
;
; Parameters:
;	None.
;
; Returns:
;	Nothing.
; Register(s) destroyed:
; 	AX
;-
check_dircmd_allowed proc near
	cmp	enable_dircmds,1
	je	@check_dircmd_allowed_99
	mov	ax,E_DIRSTK_DOS			;Assume error
	cmp	in_appl,1			;In application ?
	je	abort_dir_op			;Yes, abort
@check_dircmd_allowed_99:					;Else return
	ret
check_dircmd_allowed endp


;+
; FUNCTION : save_drv_path
;
;	Saves the current drive and path in the specified buffer in the
;	form `D:\dir1....' where the current drive letter. The buffer
;	MUST be long enough.
;
; Parameters:
;	AX	= address of save buffer
;
; Returns:
;	Nothing.
;
; Register(s) destroyed:
;	AX,DX
;-
save_drv_path	proc near
	@save	si,di
	mov	di,ax				;DI->save buffer
	@GetDrv					;AL<-drive number
	add	al,'a'				;AL<-drive letter
	stosb					;Remember current drive
	mov	al,':'
	stosb
	mov	al,'\'
	stosb
	@GetDir di				;Remember current path
	@restore
	ret
save_drv_path	endp



;+
; FUNCTION : change_drv_path
;
;	Changes the current drive and directory to the one specified.
;
; Parameters:
;	AX	->path in the form `D:\dir1\dir2\...' terminated
;		  with a 0 byte where D is the drive letter. Entire
;		  path name need no be given. It is OK if the last
;		  directory in the path is followed by a '\'.
;
; Returns:
;	CF	= 0 if current drive and directory succesfully changed,
;		  1 if any errors (drive and path both unchanged)
; Register(s) destroyed:
;-
change_drv_path proc near
	@save	si,di
	push	bp
	mov	bp,sp
	sub	sp,PATHBUF_SIZE
cur_path	equ <byte ptr [bp-PATHBUF_SIZE]>
	push	ax				;Remember new path
	lea	ax,cur_path			;AX->current path save buf
	call	near ptr save_drv_path		;Save current disk/dir
	pop	dx				;DX->new path
	mov	si,dx				;SI->new path
	mov	di,dx
	xor	al,al				;Search for terminator
	mov	cx,0ffffh
	repne	scasb				;DI->byte after NULL
	cmp	byte ptr [di-2],'\'		;Extra '\' char ?
	jne	@change_drv_path_10		;No
	;If '\' at the end, make sure it is not of the form d:\ or just \
	cmp	byte ptr [di-3],':'
	je	@change_drv_path_10
	dec	di
	dec	di				;DI->'\' character
	cmp	di,dx				;Solitary '\' ?
	je	@change_drv_path_10		;Yes
	mov	[di],al				;No, replace '\' with 0
@change_drv_path_10:
	@ChDir	dx
	jnc	@change_drv_path_80		;No error
; 	Check if error was because drive was specified but not the path.
;	In this case, we should only change the drive.
	cmp	byte ptr 2[si],0		;third byte nust be null
	jne	@change_drv_path_85		;Nope
	cmp	byte ptr 1[si],':'		;Drive specified ?
	jne	@change_drv_path_85		;Nope
	jmp	short @change_drv_path_82
@change_drv_path_80:
	cmp	byte ptr 1[si],':'		;Drive spec ?
	clc					;To indicate success
	jne	@change_drv_path_99		;No, all done
@change_drv_path_82:
	lodsb					;AL<-drive
	call	near ptr tolower
	sub	al,'a'				;AL<-drive number
	@SetDrv al				;Change the drive
	jnc	@change_drv_path_99		;No error
; 	Error, restore path, drive would not have been changed
@change_drv_path_85:
	lea	dx,cur_path
	@ChDir	dx
	stc					;Indicate error to caller
@change_drv_path_99:
	mov	sp,bp
	pop	bp
	@restore
	ret
change_drv_path endp



;+
; FUNCTION : execute_popd
;
;	Pops the topmost element off the directory stack and makes it
;	the current drive/directory.
;
; Parameters:
;	None.
;
; Returns:
;	Nothing.
;
; Register(s) destroyed:
;	AX,BX,CX,DX
;-
execute_popd proc near
	call	near ptr check_dircmd_allowed
	@save	si,di
	push	bp
	mov	bp,sp
	sub	sp,PATHBUF_SIZE
topdir	equ	PATHBUF_SIZE
	mov	bx,offset DGROUP:dir_stk	;BX->dir stack descriptor
	call	near ptr strstk_settop
	lea	ax,[bp-topdir]
	mov	cx,PATHBUF_SIZE
	call	near ptr strstk_copy		;Get top of stack
;						 String is terminated
;						 by a 0 byte
	jc	@execute_popd_90
	or	ax,ax				;Empty stack ?
	jz	@execute_popd_90		;Yes, error
	lea	ax,[bp-topdir]			;AX->new path
	call	near ptr change_drv_path	;Change drive and path
	jc	@execute_popd_90
	call	near ptr strstk_kill		;Delete top of stack
	mov	sp,bp
	pop	bp
	@restore
; Klugery - return a zero length string to DOS in order to set prompt properly.
	mov	lastchar,offset DGROUP:linebuf
	mov	user_command,1			;indicate line to be
;						 returned to DOS
	ret

@execute_popd_90:
	mov	ax,E_DIRSTK_EMPTY
	jmp	near ptr abort_dir_op
execute_popd	endp



;+
; FUNCTION : execute_pushd
;
;	If a parameter is given, pushes current directory/disk onto the
;	dir stack and changes to the parameter. If no parameter,
;	exchange the top of directory stack with current disk-directory.
;
; Parameters:
;	SI	-> first char in linebuf following this command
;	CX	= remaining num chars in line
;
; Returns:
;	Nothing.
;
; Register(s) destroyed:
;	AX,BX,CX,DX
;-
execute_pushd	proc	near
	@save	si,di
	push	bp
	mov	bp,sp
	sub	sp,2*PATHBUF_SIZE
cur_path	equ <byte ptr [bp-PATHBUF_SIZE]>
new_path	equ <byte ptr [bp-(2*PATHBUF_SIZE)]>
	call	near ptr check_dircmd_allowed
;						 Will return only if so
	push	cx				;Save line length
	lea	ax,cur_path
	call	near ptr save_drv_path		;Save current drive and path

	pop	cx				;CX<-restored line length
	call	near ptr skip_whitespace
	; SI->first non blank, CX<-num remaining chars
	jcxz	@execute_pushd_50		;Exchange directory
;						 with top of stack
	push	si				;SI->path to change to
	call	near ptr skip_nonwhite
	; SI->first non-blank
	mov	byte ptr [si],0			;Terminating 0 byte
;	We are guaranteed place for a 0 because of the dummy byte after linebuf
	pop	ax				;AX->dir to change to
	call	near ptr change_drv_path	;Change path and drive
	jc	@execute_pushd_32		;Error
@execute_pushd_25:
	lea	dx,cur_path
	call	near ptr dir_push		;Push onto stack
	jnc	@execute_pushd_100		;No error
@execute_pushd_30:
; Error. Restore original directory and display error message.
	lea	ax,cur_path
	call	near ptr change_drv_path
@execute_pushd_32:
	mov	ax,E_DIRSTK
	jmp	abort_dir_op

@execute_pushd_50:
; Exhange current directory with the directory at the top of the stack
	mov	bx,offset DGROUP:dir_stk	;BX->dir stack descriptor
	call	near ptr strstk_settop
	lea	ax,new_path
	mov	cx,PATHBUF_SIZE
	call	near ptr strstk_copy		;Get top of stack
;						 String is terminated
;						 by a 0 byte
	jnc	@execute_pushd_60
@execute_pushd_55:
	lea	ax,cur_path
	call	near ptr change_drv_path
	mov	ax,E_DIRSTK_EMPTY
	jmp	abort_dir_op
@execute_pushd_60:
	or	ax,ax				;Empty stack ?
	jz	@execute_pushd_55		;Yes, error
	lea	ax,new_path			;AX->new path
	call	near ptr change_drv_path	;Change drive and path
	jc	@execute_pushd_30
	call	near ptr strstk_kill		;Delete top of stack
	lea	dx,cur_path
	call	near ptr dir_push
	jnc	@execute_pushd_100			;All set
;	Error. Restore original top of stack
	lea	dx,new_path
	call	near ptr dir_push		;Push must succeed
	jmp	short @execute_pushd_30

@execute_pushd_100:
	mov	sp,bp
	pop	bp
	@restore
; Klugery - return a zero length string to DOS in order to set prompt properly.
	mov	lastchar,offset DGROUP:linebuf
	mov	user_command,1			;indicate line to be
;						 returned to DOS
	ret
execute_pushd	endp




;+
; FUNCTION : execute_chd
;
;	Changes to the disk and directory specified as parameter.
;
; Parameters:
;	SI	-> first char in linebuf following this command
;	CX	= remaining num chars in line
;
; Returns:
;	Nothing.
;
; Register(s) destroyed:
;	AX,BX,CX,DX
;-
execute_chd	proc	near
	@save	si,di
	push	bp
	mov	bp,sp
	sub	sp,PATHBUF_SIZE
new_path	equ <byte ptr [bp-PATHBUF_SIZE]>
	call	near ptr check_dircmd_allowed
;						 Will return only if so
	push	cx				;Save line length
	call	near ptr skip_whitespace
	; SI->first non blank, CX<-num remaining chars
	jcxz	@execute_chd_100		;No args
;						 with top of stack
	push	si				;SI->path to change to
	call	near ptr skip_nonwhite
	; SI->first non-blank
	mov	byte ptr [si],0			;Terminating 0 byte
;	We are guaranteed place for a 0 because of the dummy byte after linebuf
	pop	ax				;AX->dir to change to
	call	near ptr change_drv_path	;Change path and drive
	jnc	@execute_chd_100			;No error
	mov	ax,E_DIRSTK
	jmp	abort_dir_op

@execute_chd_100:
	mov	sp,bp
	pop	bp
	@restore
; Klugery - return a zero length string to DOS in order to set prompt properly.
	mov	lastchar,offset DGROUP:linebuf
	mov	user_command,1			;indicate line to be
;						 returned to DOS
	ret
execute_chd endp





CSEG	ENDS

	END

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -