;************************************************************************/
;*	Copyright (C) 1986-1988 Phar Lap Software, Inc.			*/
;*	Unpublished - rights reserved under the Copyright Laws of the	*/
;*	United States.  Use, duplication, or disclosure by the 		*/
;*	Government is subject to restrictions as set forth in 		*/
;*	subparagraph (c)(1)(ii) of the Rights in Technical Data and 	*/
;*	Computer Software clause at 252.227-7013.			*/
;*	Phar Lap Software, Inc., 60 Aberdeen Ave., Cambridge, MA 02138	*/
;************************************************************************/
;
; This program illustrates how MS-DOS system calls are made from
; 386 protected mode.
;

;
; Constants
;
nl	equ	00ah

_data	segment	para public use32 'data'


;
;	Messages
;

hellomsg db	'DOS demo program for 386 protected mode',0dh,0ah,0dh,0ah,'$'

strikemsg db	'Strike any key --> ',0

keymsg	db	nl,'Code of the key which you hit - ',0

nlmsg	db	nl,0

linputmsg db	'Type in a line of text --> ',0

pbmsg     db	nl,'DOS read               --> ',0

cdiskmsg db	'Current disk -- ',0

crtmsg	db	'Now creating the file "TEST.DAT"',nl,0

wrtmsg	db	'Now writing data to the file "TEST.DAT"',nl,0

closemsg db	'Now closing the file "TEST.DAT"',nl,0

openmsg	db	'Now reopening the file "TEST.DAT"',nl,0

readmsg	db	'Data from the file "TEST.DAT" -- ',0

seekmsg	db	'Data starting from byte position 5 of "TEST.DAT" -- ',0

ffmsg	db	'Name of the first file of the current directory -- ',0

sfmsg	db	'Name of the second file of the current directory -- ',0

renmsg	db	'Now renaming the file "TEST.DAT" to "NEWTEST.DAT"',nl,0

delmsg	db	'Now deleting the file "NEWTEST.DAT"',nl,0

cdirmsg db	'Current directory -- ',0

setdtamsg db	'Setting disk transfer address to -- ',0

dtamsg	db	'Disk transfer address is -- ',0

ferrmsg	db	nl,'ABORT -- File system error #',0

;
;	The input buffer
;

inbuff	db	80,0,81 dup (?)


;	
;	File variables
;

flname	db	'TEST.DAT',0		; Name of the test file
nflname	db	'NEWTEST.DAT',0		; New file name
dsrcstr	db	'*.*',0			; Directory search string
flhand	dw	?			; The file handle

fldata	db	'ABCDEFGHIJKLMNOPQRSTUVWXYZ'	; The file data
flend	label	byte				;

fdsize	equ	flend-fldata		; The size of the data

_data	ends

_stack	segment	byte stack use32 'stack'

	db	8192 dup (?)

_stack	ends

	assume	cs:_text,ds:_data

_text	segment	para public use32 'code'

	public	_start_			;
_start_	proc	near			;

;*********************************************************
; Test print string (function 09)
;*********************************************************
	lea	edx,hellomsg		; Output the hello message.
	mov	ah,09h
	int	21h

;*********************************************************
; Test keyboard and console I/O
;*********************************************************
;
; Test read keyboard (function 08) and display character (function 02, in
; subroutine printmsg)
;
	lea	ebx,strikemsg		; Ask the user to strike a key.
	call	printmsg		; 
	mov	ah,8h			;
	int	21h			;

	push	ax			; Output the hex code of the key
	lea	ebx,keymsg		;    which was struck.
	call	printmsg		;
	pop	ax			;
	call	hbout			;
	lea	ebx,nlmsg		;
	call	printmsg		;

;
; Test buffered keyboard input (function 0A)
;
	lea	ebx,linputmsg		; Read in a line of input.
	call	printmsg		;
	lea	edx,inbuff		;
	mov	ah,0ah			;
	int	21h			;

	lea	ebx,pbmsg		; Echo the line back to the screen.
	call	printmsg		;
	xor	ebx,ebx			;
	mov	bl,inbuff+1		;
	add	ebx,offset inbuff+2	;
	mov	byte ptr [ebx],00ah	;
	mov	byte ptr 1[ebx],0	;
	lea	ebx,inbuff+2		;
	call	printmsg		;

;*********************************************************
; Test disk I/O that doesn't use FCBs
;*********************************************************
;
; Test get current disk (function 19)
;
	lea	ebx,cdiskmsg		; Output the name of the current disk.
	call	printmsg		;
	mov	ah,19h			;
	int	21h			;
	add	al,'A'			;
	mov	dl,al			;
	mov	ah,2h			;
	int	21H			;
	lea	ebx,nlmsg		;
	call	printmsg		;

;
; Test create file (function 3C)
;
	lea	ebx,crtmsg		; Create a test file.
	call	printmsg		;
	lea	edx,flname		;
	mov	cx,0			;
	mov	ah,03ch			;
	int	21h			;
	call	flercheck		;
	mov	flhand,ax		;

;
; Test write to file/device (function 40)
;
	lea	ebx,wrtmsg		; Write some data in the file.
	call	printmsg		;
	mov	bx,flhand		;
	mov	ecx,fdsize		;
	lea	edx,fldata		;
	mov	ah,040h			;
	int	21h			;
	call	flercheck		;

;
; Test close file (function 3E)
;
	lea	ebx,closemsg		; Close the file.
	call	printmsg		;
	mov	bx,flhand		;
	mov	ah,03eh			;
	int	21h			;
	call	flercheck		;

;
; Test open file (function 3D)
;
	lea	ebx,openmsg		; Re-open the file.
	call	printmsg		;
	lea	edx,flname		;
	mov	al,2			;
	mov	ah,03dh			;
	int	21h			;
	call	flercheck		;
	mov	flhand,ax		;

;
; Test read from file (function 3F)
;
	lea	ebx,readmsg		; Read back the data which we
	call	printmsg		;    wrote to the file.
	mov	bx,flhand		;
	xor	ecx,ecx			;
	mov	cl,inbuff		;
	lea	edx,inbuff+2		;
	mov	ah,03fh			;
	int	21h			;
	call	flercheck		;

	mov	ebx,eax			; Print out the data which we read
	add	ebx,offset inbuff+2	;
	mov	byte ptr [ebx],0	;	
	lea	ebx,inbuff+2		;
	call	printmsg		;
	lea	ebx,nlmsg		;
	call	printmsg		;

;
; Test move file pointer (function 42)
;
	lea	ebx,seekmsg		; Seek to byte 5 of the file.
	call	printmsg		;
	mov	al,0			;
	mov	bx,flhand		;
	mov	cx,0			;
	mov	dx,5			;
	mov	ah,42h			;
	int	21h			;
	call	flercheck		;

	mov	bx,flhand		; Read from the file again.
	xor	ecx,ecx			;
	mov	cl,inbuff		;
	lea	edx,inbuff+2		;
	mov	ah,03fh			;
	int	21h			;
	call	flercheck		;

	mov	ebx,eax			; Print out the data which we read.
	add	ebx,offset inbuff+2	;
	mov	byte ptr [ebx],0	;	
	lea	ebx,inbuff+2		;
	call	printmsg		;
	lea	ebx,nlmsg		;
	call	printmsg		;

;
; Test rename file (function 56)
;
	lea	ebx,closemsg		; Close the file.
	call	printmsg		;
	mov	bx,flhand		;
	mov	ah,03eh			;
	int	21h			;
	call	flercheck		;

	lea	ebx,renmsg		; Rename the file.
	call	printmsg		;
	lea	edx,flname		;
	lea	edi,nflname		;
	mov	ah,56h			;
	int	21h			;
	call	flercheck		;

;
; Test delete file (function 41)
;
	lea	ebx,delmsg		; Delete the file.
	call	printmsg		;
	lea	edx,nflname		;
	mov	ah,41h			;
	int	21h			;
	call	flercheck		;

;
; Test get current directory (function 47)
;
	lea	ebx,cdirmsg		; Print out the name of the current
	call	printmsg		;    directory.
	mov	dl,0			;
	lea	esi,inbuff+2		;
	mov	ah,47h			;
	int	21h			;
	call	flercheck
	lea	ebx,inbuff+2		;
	call	printmsg		;
	lea	ebx,nlmsg		;
	call	printmsg		;

;
; Test get disk transfer address (function 2F)
;
	mov	ah,2Fh			; get DTA
	int	21h

	push	ebx			; save returned ES:EBX
	push	es			;
	lea	ebx,dtamsg		; Output the transfer address
	call	printmsg		;
	pop	eax			;
	call	hwout			;
	mov	dl,':'			;
	mov	ah,02h			;
	int	21h			;
	pop	eax			;
	call	hlout			;
	lea	ebx,nlmsg		;
	call	printmsg		;

;
; Test set disk transfer address (function 1A)
;
	lea	ebx,setdtamsg		; Output the transfer address
	call	printmsg		;    we will set the DTA to
	mov	ax,ds			;
	call	hwout			;
	mov	dl,':'			;
	mov	ah,02h			;
	int	21h			;
	lea	eax,inbuff+2		;
	call	hlout			;
	lea	ebx,nlmsg		;
	call	printmsg		;
	lea	edx,inbuff+2		; Set the DTA.
	mov	ah,1ah			;
	int	21h			;

	mov	ah,2Fh			; get DTA
	int	21h			;
	push	ebx			; save returned ES:BX
	push	es			;
	lea	ebx,dtamsg		; Output the transfer address
	call	printmsg		;
	pop	eax			;
	call	hwout			;
	mov	dl,':'			;
	mov	ah,02h			;
	int	21h			;
	pop	eax			;
	call	hlout			;
	lea	ebx,nlmsg		;
	call	printmsg		;

;
; Test find matching file (4E)
;
	lea	ebx,ffmsg		; Print out the name of the first
	call	printmsg		;    file in the current directory.
	lea	edx,dsrcstr		;
	mov	ecx,0			;
	mov	ah,4eh			;
	int	21h			;
	call	flercheck		;
	lea	ebx,inbuff+2+30		;
	call	printmsg		;
	lea	ebx,nlmsg		;
	call	printmsg		;

;
; Test find next matching file (function 4F)
;
	lea	ebx,sfmsg		; Print out the name of the second 
	call	printmsg		;    file in the directory.
	mov	ah,04fh			;
	int	21h			;
	call	flercheck		;
	lea	ebx,inbuff+2+30		;
	call	printmsg		;
	lea	ebx,nlmsg		;
	call	printmsg		;

;*********************************************************
; Test terminate process (function 4C)
;*********************************************************
	mov	ax,04c00h		; Exit back to DOS.
	int	21h			;

_start_	endp				;


;	
;	printmsg - Print a message to the screen
;
;	ebx - Points to the message to be printed out.  The message
;	      must be null terminated.
;

printmsg proc	near

	push	edx			; Save EDX.

#1:	mov	dl,[ebx]		; Load the next character into DL and
	or	dl,dl			;    branch if null.
	je	#3			;

	mov	ah,02h			; Output the character.
	int	21h			;

	cmp	byte ptr [ebx],0ah	; If the character is a LF, then
	jne	#2			;    also output a CR.
	mov	ah,02h			;
	mov	dl,0dh			;
	int	21h			;

#2:	add	ebx,1			; Increment the message pointer and
	jmp	#1			;    loop.

#3:	pop	edx			; Restore EDX and return.
	ret				;

printmsg endp				;


;
; 	hlout - Output the hex long word in EAX to the screen
;

hlout	proc	near			;

	push	eax			; Output the high word of the long. 
	ror	eax,16			;
	call	hwout			;

	pop	eax			; Output the low word of the long.
	call	hwout			;

	ret				; Return.

hlout	endp				;


;
; 	hwout - Output the hex word in AX to the screen
;

hwout	proc	near			;
		
	push	ax			; Output the high byte of the word.
	ror	ax,8			;
	call	hbout			;

	pop	ax			; Output the low byte of the word.
	call	hbout			;

	ret				; Return.

hwout	endp				;


;
; 	hbout - Output the hex byte in AL to the screen
;

hbout	proc	near			;
		
	push	ax			; Output the high digit of the byte.
	ror	ax,4			;
	call	hdout			;

	pop	ax			; Output the low digit of the byte.
	call	hdout			;

	ret				; Return.

hbout	endp


;
; 	hdout - Output the hex digit in AL to the screen
;

hdout	proc	near

	and	ax,0fh			; Zap any extra bits and translate
	cmp	ax,10			;    to ASCII.
	jge	#1			;
	add	al,'0'-'A'+10		;
#1:	add	al,'A'-10		;

	push	dx			; Call MS-DOS to output the digit.
	mov	dl,al			;
	mov	ah,2h			;
	int	21h			;
	pop	dx			;

	ret				; Return.

hdout	endp


;	
;	flercheck - File error check
;

flercheck proc	near

	jc	#1			; Make a quick return if no error.
	ret				;

#1:	push	ax			; Save the error code.

	lea	ebx,ferrmsg		; Output an error message.
	call	printmsg		;

	pop	ax			; Output the DOS error code.
	call	hwout			;

	lea	ebx,nlmsg		; Output a new line.
	call	printmsg		;

	mov	ax,04c01h		; Exit back to MS-DOS.
	int	21h			;

flercheck endp				;

_text	ends

	end _start_
