	.TITLE	REVERSE	- A program to demo simple I/O from MACRO
	.IDENT	/01-000/
;++
;
;  Facility:	REVERSE
;
;  Author:	Hunter Goatley
;
;  Date:	May 31, 1991
;
;  Functional Description:
;
;	Simple program to read a string from SYS$INPUT and print it in
;	reverse order to SYS$OUTPUT.
;
;  Modified by:
;
;	01-000		Hunter Goatley		31-MAY-1991 08:02
;		Original version.
;
;--
	.DSABL	GLOBAL				; Declare external references
	.ENABL	SUPPRESSION			; Don't list unreference symbols
	.NOSHOW	BINARY				; Don't include binary listings
;
;  External routines:
;
	.EXTRN	LIB$GET_INPUT			; Read from SYS$INPUT
	.EXTRN	LIB$PUT_OUTPUT			; Print to SYS$OUTPUT
;
;  Declare symbols used here (the following macros are stored in the default
;  MACRO library SYS$LIBRARY:STARLET.MLB).
;
	$DSCDEF					; Descriptor symbols
	$SSDEF					; System service status symbols

	.SHOW	BINARY				; Include binary in listings

	.PAGE
	.SBTTL	Data storage
	.PSECT	_REVERSE_DATA,NOEXE,WRT,LONG

PROMPT:		.ASCID	/Enter a string: /	; Prompt for input
		.ALIGN	LONG			; Align on longword boundary
;
;  Descriptor for input buffer
;
INBUFF_L = 256					; Length of the buffer
INBUFF_D:	.WORD	INBUFF_L		; Length of the buffer
		.BYTE	DSC$K_DTYPE_T		; Text string
		.BYTE	DSC$K_CLASS_S		; Static string
		.ADDRESS INBUFF			; Address of the buffer

INBUFF:		.BLKB	INBUFF_L		; Reserve space for the buffer
;
;  Descriptor for the output buffer
;
OUTBUFF_D:	.WORD	0			; Length filled in at run-time
		.BYTE	DSC$K_DTYPE_T		; Text string
		.BYTE	DSC$K_CLASS_S		; Static string
		.ADDRESS .+4			; Address of the buffer
		.BLKB	INBUFF_L		; Reserve space for buffer

	.PAGE
	.SBTTL	The Program

	.PSECT	_REVERSE_CODE,EXE,NOWRT,LONG
	.ENTRY	REVERSE,^M<R2>
;
;  Call run-time library routine to read input from SYS$INPUT
;
	PUSHAW	INBUFF_D			; Address of word to receive
						; ... the length of the input
	PUSHAQ	PROMPT				; Address of the prompt
	PUSHAQ	INBUFF_D			; Address of the input buffer
						; ... descriptor
	CALLS	#3,G^LIB$GET_INPUT		; Read input from SYS$INPUT
	BLBC	R0,100$				; Branch on an error
;
;  Now set up some registers to contain the values needed to copy the string
;  in reverse order from the input buffer to the output buffer.
;
;  First, make R2 point to the end of the input buffer
;
	MOVAB	INBUFF,R2			; R2 -> input buffer
	MOVZWL	INBUFF_D,R0			; R0 = length of the input
						; ... (converted to longword)
	ADDL2	R0,R2				; R2 -> byte past end of buffer
;
;  Since the output string will the the same length as the input string, go
;  ahead and copy the length of the string the output buffer descriptor.
;
	MOVW	R0,OUTBUFF_D			; Store length in descriptor
	MOVAB	@OUTBUFF_D+4,R1			; R1 -> output buffer
;
;  The following loop copies the input string to the output buffer a byte
;  at a time, moving backwards through the input buffer and forward through
;  the output buffer.
;
;  At this point, the following registers contain the following values:
;
;	R0	= Number of character to copy
;	R1	= Pointer to beginning of output buffer
;	R2	= Pointer to end of input buffer
;
 10$:	MOVB	-(R2),(R1)+			; Copy byte from input buffer
						; ... to the output buffer
	SOBGTR	R0,10$				; Loop until all copied

	PUSHAQ	OUTBUFF_D			; Print the output buffer
	CALLS	#1,G^LIB$PUT_OUTPUT		; ... to SYS$OUTPUT

 100$:	RET					; Return to caller

	.END	REVERSE
