4.3	A Sample Random Access Program	CP/M 3 Programmer's Guide


Instead of reading a number, the QUERY program reads an 
alphanumeric string
which is a particular key to find in the NAMES.DAT data base. 
Because the LAST-
NAME.KEY list is sorted, you can find a particular entry quickly 
by performing a
binary search, similar to looking up a name in the telephone 
directory. Start at both
ends of the list and examine the entry halfway in between and, if 
not matched, split
either the upper half or the lower half for the next search. You 
will quickly reach the
item you are looking for, in log2(n) steps, where you will find 
the corresponding
record number. Fetch and display this record at the console as 
the program illustrates.

	At this point, you are just getting started. With a little more 
work, you can allow
a fixed grouping size, which differs from the 128-byte record 
shown above. You can
accomplish this by keeping track of the record number as well as 
the byte offset
within the record. Knowing the group size, you can randomly 
access the record
containing the proper group, offset to the beginning of the group 
within the record,
and read sequentially until the group size has been exhausted.

	Finally, you can improve QUERY considerably by allowing Boolean 
expressions
that compute the set of records that satisfy several 
relationships, such as a LAST-
NAME between HARDY and LAUREL and an AGE less than 45. Display 
all the
records that fit this description. Finally, if your lists are 
getting too big to fit into
memory, randomly access your key flIes from the disk as well.


4.4	Construction of an RSX Program

	This section describes the standard prefix of a Resident System 
Extension (RSX)
and illustrates the construction of an RSX with an example. (See 
Section 1.6.4 for a
discussion of how RSXs operate under CP/M 3.) RSX programs are 
usually written
in assembler, but you can use other languages if the interface 
between the language
and the calling conventions of the BDOS are set up properly.
CP/M 3 Programmer's Guide	4.4  Construction of an RSX Program


4.4.1	TheRSXPrefix

	The first 27 bytes of an RSX program contain a standard data 
structure called the
RSX prefix. The RSX prefix has the following format:

serial:
	db	0,0,0,0,0,0
start:
JMP  ftest	; start of program
next:
	db	Oc3h	;	JUMP instruction to
	dw	0	; next Module in line
	prev:
	dw	0	; previous module
	remove:
	db	0ffh	;	remove flag
	n 0 fl b a ri k:
	db	0	; nonbanK flag
	n a m e:
	db	'12345678'	; any 8_character name
	loader:
	db	0	;	loader flag
	db	0,0	;	reserved area

	The only fields of the RSX prefix that you must initialize are 
the remove: flag, the
nonbank: flag, and the name: of the RSX.

	For compatibility with previous releases of CPIM, the serial: 
field of the prefix is
set to the serial number of the operating system by the LOADER 
module when the
RSX is loaded into memory. Thus, the address in location 6 
locates the byte follow-
ing the serial number of the operating system with or without 
RSXs in memory.

	The start: field contains a jump instruction to the beginning of 
the RSX code
where the RSX tests to see if this BDOS function call is to be 
intercepted or passed
on to the next module in line.

	The next: field contains a jump instruction to the next module in 
the chain or the
LOADER module if the RSX is the oldest one in memory. The RSX 
program must
make its own BDOS function calls by calling the next: entry 
point.
4.4	Construction of an RSX Program	CP/M 3 Programmer's Guide


	The prev: field contains the address of the preceding RSX in 
memory or location S
if the RSX is the first RSX in the chain.

	The remove: field controls whether the RSX is removed from memory 
by the next
call to the LOADER module via BDOS function 59. 1f the remove: 
flag is OFFH, the
LOADER removes the RSX from memory. Note that the CCP always 
calls the
LOADER module during a warm start operation. An RSX that rcmains 
in memory
past warm start because its remove: flag is zero, must set the 
flag at its termination
to ensure its removal from memory at the following warm start.

	The nonbank: field controls when the RSX is loaded. 1f the field 
is OFFH, the
LOADER only loads the module into memory on nonbanked CP/M 3 
systems.
Otherwise, the RSX is loaded into memory under both banked and 
nonbanked ver-
sions of CP/M 3.

	The loader: flag identifies the LOADER RSX. When the LOADER 
module loads
an RSX into memory, it sets this prefix flag of the loaded RSX to 
zero. However, the
loader: flag in the LOADER's prefix contains 0FFH Thus, this flag 
identifies the last
RSX in the chain, which is always the LOADER.

4.4.2	Example of RSX Use

	These two sample programs illustrate the use of an RSX program. 
The first
program, CALLVERS, prints a message to the console and then makes 
a BDOS
Function 12 call to obtain the CP/M 3 version number. CAL LVERS 
repeats this
sequence five times before terminating. The second program, 
ECHOVERS, is an RSX
that intercepts the BDOS Function 12 call made by CALLVERS, 
prints a second
message, and returns the version 0031H to CALLVERS. Although this 
example is
simple, it illustrates BDOS function interception, stack 
swapping, and BDOS function
calls within an RSX.
CP/M 3 Programmer's Guide	4.4	Construction of an RSX Program
			; CALLVERS program
	0005	=	bdos	equ	5	;	entrY point for BDOS
	000B	=	prtstr	equ	B	;	print string funCtion
	000C	=	vers	equ	12	;	get version function
	000D	=	cr	equ	Odh	;	carriage  return
	OOOA	=	lf	equ	Oah	;	line feed
	0100			org	l00h
	0100	1605		mvi	d,5	;	Perform 5 times
	0102	DS	loop:	push	d	;	save counter
	0103	OEOB		mvi	c,Prtstr
	0105	111e01		lxi	d,call$msg	;	Print call message
	oioe	CDOSOO		call	bdos
	OlOB	OEOC		mvi	c,vers
	0l0D	CDO5OO		call	bdos	;	trY to get version *
						;	CALLVERS will  intercept
	0110	7D		mov	a,l
	0111	323401		sta	curvers
	0114	d1		pop	d
	0115	15		dcr	d	;	decrement counter
	0116	C20201		Jnz	loop
	0119	0E00		mvi	c,0
	OllB	C30500		JmP	bdos
			call $ms g:
	011C	ODOA2A2A2A		db	cr,lf,'****	CALLVERS **** $'
	0134	00	curvers	db	0
	0135			end
	; ECHOVERS RSX
	000B	=	pstring	equ	9	; string Print function
	000D	=	cr	equ	Odh
OOOA =	lf	equ	Oah
	'		RSX PREFIX STRUCTURE
	0000	0000000000		db	0,0,0,0,0,0	;	room for serial number
	0006	C3lBOO		Jmp	ftest	;	begin of Program
	0005	C3	next:	db	Oc3H	;	Jump
	OOOA	0000		dw	0	; next module in line
	000C	0000	prev:	dw	0	;	previous module
	000c	FF	remov:	db	0ffh	;	remove flag set
	OOOF	00	nonbnk:	db	0
	0010	4543484F56		db	'ECHOVERS'
	0018	000000		db	0,0,0
4.4	Construction of an RSX Program	CP/M 3 Programmer's Guide
			ftest:			;	is this function 12?
	OO1B	79		mov	a,c
	OO1C	FEOC		cpi	12
	OO1E	CA2400		Jz	begin	;	Yes - intercept
	0021	C30500		Jmp	next	;	some other function
			begin:
	0024	210000		lxi	h,0
	0027	39		dad	sp	; save stack
	0028	225400		shld	ret$stack
	002B	317600		lxi	sp,loc$stack
	002E	OEOS	mvi	c,pstring
	0030	113E00	lxi	d,test$msg	; Print message
	0033	CDO9OO	call	next	; call BDDS
	0036	2A5400		lhld	ret$stack	;	restore user stack
	0039	F9		sphl
	003A 213100	lxi	h,0031h	;  return version number
003D C9	ret
			test$msg:
	003E	ODOA2A2A2A	db 	cr,lf,'**** ECHDVERS ****$'
			ret$s tack:
	0054	0000	dw 	0
	0056		ds 	32                  ;  16 level stack
			loc$stack :
	0076		end
CP/M 3 Programmers Guide	4.4  Construction of an RSX Program


You can prepare the above programs for execution as follows:

1.	Assemble the CALLVERS program using MAC as follows:
MAC CALLVERS
	2 Generate a COM file for CALLVERS with HEXCOM:
HEXCOM CALLVERS

3.	Assemble the RSX program ECHOVERS using RMAC:
RMAC ECHOVERS

4.	Generate a PRL file using the LINK command:
LINK ECHOVERS [OP]

5.	Rename the PRL file to an RSX file:
RENAME ECHOVERS.RSX=ECHOVERS.PRL
6.	Generate a COM file with an attached RSX using the GENCOM 
command:
GENCOM CALLVERS ECHOVERS
7.	Run the CALLVERS.COM module:
CALLVERS
The message
****	CALLVERS ****
followed by the message
****	ECHOVERS ****
appears on the screen five times if the RSX program works.


End of Section 4
Appendix A
System Control Block

	The System Control Block (SCB) is a CP/M 3 data structure located 
in the BDOS
CP/M 3 uses this region primarily for communication between the 
BDOS and the
BIOS. However, it is also available for communication between 
application pro-
grams, RSXs, and the BDOS Note that programs that access the 
System Control
Block are not version independent. They can run only on CP/M 3.

	The following list describes the fields of the SCB that are 
available for access by
application programs and RSXs. The location of each field is 
described as the offset
from the start address of the SCB (see BDOS Function 49). The 
RW/RO column
indicates if the SCB field is Read-Write or Read-Only.


Table A-i. SCB Fields and Definitions
	Offset	RW/RO	Definition
00 - 04	RO	Reserved for system use.
05	RO	BDOS Version Number.
06 - 09	RW	Reserved for user use. Use these four bytes for your

own flags or data.
0A - 0F	RO	Reserved for system use.
10 - 11	RW	Program Error Return Code. This 2-byte field can be
		used by a program to pass an error code or value to a
		chained program. CP/M 3's conditional command facil
		ity also uses this field to determine if a program exe
		cutes successfully. The BDOS Function 108 (Get/Set
		Program Return Code) is used to get/set this value.
12 - 19	RO	Reserved for system use.
A   System Control Block	CP/M 3 Programmer's Guide


Table A-i. (continued)
	Offset	RW/RO	Definition
lA	RW	Console Width. This byte contains the number of col
		umns, characters per line, on your console relative to
		zero. Most systems default this value to 79. You can
		set this default value by using the GENCPM or the
		DEVICE utility. The console width value is used by the
		banked version of CP/M 3 in BDOS function 10,
		CP/M 3's console editing input function, Note that typ
		ing a character into the last position of the screen, as
		specified by the Console Width field, must not cause
		the terminal to advance to the next line.
lB	RO	Console Column Position. This byte contains the cur
		rent console column position.
	1 C	RW	Console Page Length. This byte contains the page length,
			lines per page, of your console. Most systems default
			this value to 24 lines per page. This default value may
			be changed by using the GENCPM or the DEVICE util
			ity (see the CP/M Plus (CP/M Version 3) Operating
			System User's Guide).
	1d - 21	RO	Reserved for system use.
22 - 2B	RW	Redirection flags for each of the five logical character
		devices. 1f your system's BIOS supports assignment of
		logical devices to physical devices, you can direct each
		of the five logical character devices to any combination
		of up to 12 physical devices. The 16-bit word for each
		device represents the following:
		Each bit represents a physical device where bit 15 cor
		responds to device zero and bit 4 corresponds to device
		11. Bits zero through 3 are reserved for system use.
		You can redirect the input and output logical devices
		with the DEVICE command (see CP/M Plus (CP/M
		Version 3) Operating System User's Guide).
CP/M 3 Programmer's Guide	A  System Control Block


Table A-i. (continued)
	Offset	RW/RO	Definition
	22 - 23	RW	CONIN Redirection Flag.
	24 - 25	RW	CONOUT Redirection Flag.
	26 - 27	RW	AUXIN Redirection Flag.
	28 - 29	RW	AUXOUT Redirection Flag.
	2A - 2B	RW	LSTOUT Redirection Flag.
	2C	RW	Page Mode. 1f this byte is set to zero, some CP/M 3
			utilities and CCP built-in commands display one page
			of data at a time; you display the next page by pressing
			any key. 1f this byte is not set to zero, the system dis
			plays data on the screen without stopping. To stop and
			start the display, you can press CTRL-S and CTRL-Q,
			respectively.
	2D	RO	Reserved for system use.
	2E	RW	Determines if CTRL-H is interpreted as a rub/del char
			acter. 1f this byte is set to 0, then CTRL-H is a back
			space character (moves back and deletes). 1f this byte is
			set to OFFH, then CTRL-H is a rub/del character, echoes
			the deleted character.
	2F	RW	Determines if rub/del is interpreted as CTRL-H charac
			ter. 1f this byte is set to 0, then rub/del echoes the deleted
			character. 1f this byte is set to OFF, then rub/del is inter
			preted as a CURL-H character (moves back and deletes).
	30 - 32	RO	Reserved for system use.
	33 - 34	RW	Console Mode. This is a 16-bit system parameter that
			determines the action of certain BDOS Console I/O
			functions. (See Section 2.2.1 and BDOS Function 109,
			Get/Set Console Mode, for a thorough explanation of
			Console Mode.)
A  System Control Block	CP/M 3 Programmer's Guide


Table A-1. (continued)
	Offset	RW/RO	Definition
35 - 36	RO	Reserved for system use.
	37	RW	Output delimiter character. The default output delim
			iter character is $, but you can change this value by
			using the BDOS Function 110, Get/Set Output Delimiter.
	38	RW	List Output Flag. lf this byte is set to 0, console output
			is not echoed to the list device. lf this byte is set to 1
			console output is echoed to the list device.
39 - 3B	RO	Reserved for system use.
3C - 3D	RO	Current DMA Address. This address can be set by BDOS
		Function 26 (Set DMA Address). The CCP initializes
		this value to 0080H BDOS Function l3, Reset Disk
		System, also sets the DMA address to 0080H
3E	RO	Current Disk. This byte contains the currently selected
		default disk number. This value ranges from 0-15 cor
		responding to drives A-P, respectively. BDOS Function
		25, Return Current Disk, can be used to determine the
		current disk value.
3F - 43	RO	Reserved for system use.
44	RO	Current User Number. This byte contains the current
		user number. This value ranges from 0-15. BDOS Func
		tion 32, Set/Get User Code, can change or interrogate
		the currently active user number.
45 - 49	RO	Reserved for system use.
	4A	RW	BDOS Multi-Sector Count. This field is set by BDOS
			Function 44, Set Multi-Sector Count.
CP/M 3 Programmer's Guide	A  System Control Block


Table A-1. (continued)
	Offset	j	RW/RO	Definition
	4B	RW	BDOS Error Mode. This field is set by BDOS Function
			45, Set BDOS Error Mode.
			1f this byte is set to OFFH, the system returns to the
			current program without displaying any error messages.
			1f it is set to OFEH, the system displays error messages
			before returning to the current program. Otherwise, the
			system terminates the program and displays error mes
			sages. See description of BDOS Function 45, Set BDOS
			Error Mode, for discussion of the different error modes.
	4C - 4F	RW	Drive Search Chain. The first byte contains the drive
			number of the first drive in the chain, the second byte
			contains the drive number of the second drive in the
			chain, and so on, for up to four bytes. 1f less than four
			drives are to be searched, the next byte is set to 0FFH
			to signal the end of the search chain. The drive values
			range from 0-16, where 0 corresponds to the default
			drive, while 1-16 corresponds to drives A-P, respec
			tively. The drive search chain can be displayed or set
			by using the SETDEF utility (see CP/M Plus (Version 3)
			Operating System User's Guide).
	50	RW	Temporary File Drive. This byte contains the drive
			number of the temporary file drive. The drive number
			ranges from 0-16, where 0 corresponds to the default
			drive, while 1-16 corresponds to drives A-P, respectively.
	51	RO	Error drive. This byte contains the drive number of the
			selected drive when the last physical or extended error
			occurred.
	52 - 56	RO	Reserved for system use.
A  System Control Block	CP/M 3 Programmer's Guide


Table A-1. (continued)
	Offset	RW/RO	Definition
	57	RO	BDOS Flags. Bit 7 applies to banked systems only. lf
			bit 7 is set, then the system displays expanded error
			messages. The second error line displays the function
			number and FCB information. (See Section 2.3.13).
			Bit 6 applies only to nonbanked systems. lf bit 6 is set,
			it indicates that GENCPM has specified single alloca
			tion vectors for the system. Otherwise, double alloca
			tion vectors have been defined for the system. Function
			98, Free Blocks, returns temporarily allocated blocks to
			free space only if bit 6 is reset.
58 - 59	RW	Date in days in binary since 1 Jan 78.
5A	RW	Hour in BCD (2-digit Binary Coded Decimal).
SB	RW	Minutes in BCD.
SC	RW	Seconds in BCD.
SD - SE	RO	Common Memory Base Address. This value is zero for
		nonbanked systems and nonzero for banked systems.
SF -- 63	RO	Reserved for system use.



End of Appendix A
