Chapter 5, Part I.  Variables ($).
Chapter 5, Part II.  The Compiling Operator (C).
Chapter 5, Part III.  The OS Interface (_, K, k, `).
:		Chapter 5.  Variables, the Compiling Operator
			    and the CP/M Interface

	Variables in REC consist of an array of two-byte words (four-byte 
words in MC68000 REC) which the programmer may use to store data or addresses 
of data.  A single operator gives access to this array, as well as to the 
array of subroutine names; we now describe this operator.

     Operator			Function performed

	$	Takes a one- or two-byte argument from the PDL, whose value 
		lies between 0 and 127, and replaces it with the address 
		belonging to that number in the variable and subroutine name 
		table.  Values between 0 and 32 and the value 127 are used as 
		variables, as they correspond to control characters in the 
		ASCII alphabet and thus are not used as subroutine names; 
		values from 33 to 126 correspond to the  ASCII printing 
		characters, which may be used as subroutine names (except @ 
		and }).




	Operator $ is almost always used together with operators S and r, 
which allow the program to store and retrieve data (c.f. Chapter 3), 
respectively.  For instance, 'FA'25$S leaves the pair of ASCII characters FA 
in the table cell corresponding to variable 25; 'm'$r leaves on the PDL, in 
place of the letter m, the address at which subroutine m starts (so that 
'm'$r@@ has the same effect as 'm'@@ or @m).

	If one wants to put aside a datum whose length is other than two 
bytes, the PDL may be used to hold it and a variable may contain its PDL 
address.  For example, an address may be used to keep the address of a File 
Control Block (FCB) created as shown in Chapter 3.  We reproduce here the 
corresponding subroutines with slight modifications, together with a new 
subroutine which calls the previous two subroutines and stores in variables 
30 and 31 the addresses of two blocks corresponding to the command line tail 
filenames appearing at locations 005CH and 006CH.

	[creates an FCB for the file whose name starts at the given address]
	(m 33 c pG n 12G &S;) M
	[clears the upper 21 bytes of an FCB]
	(pG 12+ 21 w 0% (f:;) w;) C
	[makes FCBs for the filenames at 5C and 6C]
	('05C'H@M@C 30$S '06C'H@M@C 31$S;) F

	It can be seen that subroutine M has been generalized so that it 
receives in the PDL the address from which it is to obtain the name of the 
file whose FCB it makes, instead of using a fixed address; also, it no longer 
types the address of the created block. Subroutine C uses the workspace 
operators w and f to fill with zeros the upper 21 bytes of the FCB.  Once 
subroutine F has been called, and as long as the blocks are not lifted from 
the PDL, 30$r and 31$r may be used to retrieve the addresses of the FCBs and 
thus have access to them, no matter how many more arguments have been piled 
up on the PDL.  These subroutines may be improved so that blocks are not made 
for files whose names are entirely blank; this is easily accomplished by the 
tests '05D'H1G" "= and '06D'H1G" "=, since if the first character of the 
filename is a blank, it is certain that the rest of the name is also blank.

	The PDL complement may also be used to store data.  In this case, the 
combination ml20$s, for example, stores in variable 20 the value of pz where 
the datum sent to the PDL complement by m starts.  As long as n is not used 
to remove this datum, we can use, in this example, the combination 20$ryG to 
put on the normal end of the PDL a copy of the stored datum without 
disturbing the PDL complement's contents.




	We now extend the parsing program given towards the end of Chapter 4 
so that it evaluates the parsed expression, if the parse succeeds.  
Evaluation will require that in all exponentiations the exponent be an 
integer.  The program also establishes precedence and associativity rules for 
operators, as follows:

	(a)	Expressions enclosed in parentheses are evaluated 
		first.

	(b)	** and ^ are evaluated before * and /; * and / are 
		evaluated before + and -.

	(c)	** and ^ associate from right to left; e.g., 2^3^2 is 
		evaluated as 2^(3^2), whose is different from that of 
		(2^3)^2

	(d)	* and / associate from left to right; e.g., 4*5/6 is 
		evaluated as (4*5)/6, whose value is different to 
		that of 4*(5/6)

	(e)	+ and - associate from left to right.


	The complete program is the following:

	[Algebraic notation arithmetic expression evaluator]
	{("0""9"Mz;) d				[digit]
	 (@d:;) D				[0 o more digits]
	 (qL('E'Ez;'D'Ez;)(@a;;) @d@D L;Yj;) E	[power of 10 factor]
	 (Z< (@d@D'.'Ez; J'.'Ez@d; J@d; Jj>)
		 >@D@E;) q			[number]
	 ('+'Ez; '-'Ez;) a			[additive operator]
	 ('*'Ez; '/'Ez;) m			[mult. operator]
	 ('**'Ez; '^'Ez;) i			[exp. operator]
	 (@i; @m; @a;) o			[operator]
	 (@q; '('Ez @e ')'Ez;) p		[operand]
	 (Z<(@p;J@a@p;J>)>
		(qL@o@pL:Y;);) e		[expression]

	 (					[final adjustment]
	  J('+'ED; '-'Ej'0'I;;)			[initial +, -]
	  J('(+'FAD:;) J('(-'FAj'0'I:;)		[other unary +, -]
	  J('**'FD'^'I:;)			[all ** to ^]
	  J 0,127$S 0m ;) A			[initialize]


	 (					[evaluate the formula]
	  ('(' ED @(:				[nest down]
	   ')' ED @):				[nest up]
	   Z<@q JQDO>: >			[number to the PDL]
	   @i 4 @c:				[operator ^]
	   @m 2 @c:				[operator * o /]
	   @a 1 @c: ;)				[operator + o -]
	  (n0=; Ln @@:) ;) f			[evaluate pending]

	 (127$r5+,127$S;) (			[nest down]
	 (127$r5-,127$S;) )			[nest up]

	 (					[compute or push]
	  127$r+				[add nest weight]
	  (pG lyG N				[compare weights]
	   I 					[new smaller, store]
	   nL					[lift previous weight]
	   n @@					[evaluate previous]
	   QD:					[get weight, repeat]
	   ;)
	  5/ 5* & (4= 3;;) +			[reduce ^ weight]
	  BQD mm;) c

	 (+;) +   (-;) -   (*;) *		[addn, subt, prod]

	 (/					[division]
	  p&L4N					[integer?]
	  &L;					[yes, lift residue]
	  ;) /					[no, exit]

	 (					[a^b]
	  p4(N)					[integer expt.?]
	   "Error in exponent "TLL%:		[no, reduce to int]
	  L					[yes, go on]
	  ((p&L 2=				[exponent sign]
	    pG32767;LpG00&;)			[2 or more bytes?]
	    N;					[positivo: exit]
	    ~m					[no, check base]
	    (d^) "0**x, x<0" T_;		[base 0, abort]
	    1&@/n;)				[not 0, reciprocal]
	  1m					[initial factor]
	  (d^)					[expt. = 0?]
	   (d					[yes; base = 0?]
	    ^ Ln;				[no, result=base]
	    "0**0"T_;);				[0**0, abandon]

[^ cont.]  (dd^^					[expt. = 1?]
	   2/ &					[no, divide]
	   (d					[residue 1?]
	    L &pGn * m;				[yes, multiply]
	    &;)					[no]
	   pG * &:				[square]
	   n*;)					[last product]
	 ;) ^					[end of subroutine ^]

	 (R 13%=""; T@J|;) J			[get line]
	 (2573TL '> 'TL @J ""=;
	  JZD I @e (A) @A @f '='TL#TL: ": no" TL:)}  [main]

	This program is intended to be compiled and run with REC80F, REC86F 
or REC87, the REC versions with floating point arithmetic.  It could be run 
with REC80 or REC86, whose arithmetic operators recognize only (integer) 
operands up to 2 bytes in length.  In any case, the division subroutine / may 
give apparently strange results when its operands are two-byte integers, 
since, as it was explained in Chapter 3, division of operands of this type 
considers them to be unsigned quantities, so that the expression 4/(-1), to 
give an example, causes the program to return 0 as the result, because the 
operation carried out in effect is 4/65535.

	The operation of the program shown above is the following:  Once 
subroutine e has succeeded in parsing an arithmetic expression, the main 
program calls subroutine A to eliminate all unary +'s, convert all unary -'s 
to binary operators by inserting zeros and change all **'s to ^'s.  When this 
is done, subroutine f is called to evaluate the expression, which is done by 
reading it left to right.  

	The precedence rules we stated before are implemented by assigning 
weights to the operands, so that + and - have weight 1, * and / are assigned 
a weight of 2, and ^ gets a weight of 4 (the larger the weight, the greater 
the precedence of evaluation); variable 127 is used to keep track of how 
deeply parentheses have been nested, in the form of a multiple of 5, which is 
added to the weight of operators found at that parenthesis level; this 
guarantees that all of the operators contained within a given parenthesis 
level have higher precedence than operators at an outer level.  Associativity 
is dictated by the evaluation algorithm contained in subroutine c, which 
stacks operators on the PDL complement or executes them (by using predicate 
@@) depending on the relation between the weight of the operator submitted to 
it by subroutine b and that of the top operator on the PDL complement (which 
contains 0 initially); the associativity rule for ^ demands that its weight 
be reduced when a comparison requires this operator to become stacked.

:	 	Ch. 5, Part II.  The Compiling Operator.

	Before going on to describe the compiling operator C, it is 
convenient to mention some features of the compiling area.  This area has 
associated with it three pointers: c0, c1 and c2, which point to the physical 
lower bound, the next available address and the physical upper bound of the 
compiling area, respectively.  Once REC has compiled a program (as a result 
of its own execution, not that of operator C), the value of c1 is preserved 
throughout the execution of the compiled program, which occupies memory 
bracketed by c0 and c1; c1 is stored during execution of C and is restored 
once C has performed its function.  We proceed now to the description.

     Operator			Function performed

	C	Compiles a REC program, consulting the PDL for data on the 
		program's source and the address at which the compiled 
		program is to reside; besides leaving the compiled program at 
		the desired location, C leaves two addresses on the PDL, the 
		starting address of the object (as top argument) and the 
		address following the object's last one (usually the next 
		available address in the compiling area) as the PDL's lower 
		argument.
		
  C (cont.)	The argument indicating tha address at which the object is to 
		start must be the top one on the PDL and may have either of 
		two forms: the null string or an address (in two bytes); the 
		null string indicates that the program compiled by C must 
		start following the program initially compiled by REC and an 
		address indicates the actual address where the compiled 
		program is to begin.  In general, the address provided in the 
		latter alternative should be one of those returned by a 
		previous use of C.  The lower argument, which indicates the 
		source of the REC program, may have one of three forms:  the 
		null string, indicating the source is the console keyboard, a 
		one-byte argument indicating the source is a disk file 
		residing in the disk unit designated by that byte, or a 
		two-byte argument representing a length and indicating that 
		the source program is in memory.  The last two options imply 
		that still one more argument must be on the PDL with one 
		exception noted below; in the first case it should be a 
		string of up to 11 characters giving the name and extension 
		of the disk file (the extension is assumed to be REC if not 
		included explicitly); in the second case the additional 
		argument is the starting address of the source program and 
		must be a two-byte argument (four bytes are also allowed in 
		the 8086 version).
  C (concl.)	The exception occurs when a two-byte argument representing a 
		length is zero, in which case no more arguments are sought 
		and, instead of compiling, C leaves on the PDL an address c1' 
		and a length c2-c1', where c1' is the address determined by 
		the destination argument given to C.  In the 8086 version c1' 
		is four bytes long; the upper word contains the value of the 
		code segment base.

	If C is given an address lower than c1 for the object program's 
start, the compiled program will be written over the original program, the 
most likely result being a processor "hang", i.e., that the computer ceases 
to respond.  Because of this, some care should be exercised in choosing the 
argument indicating the address and should normally be the null string 
(implyimg the use of the fixed value of c1) or one of the addresses left by C 
on the PDL. 

	When REC or the operator C compile a program whose last address 
exceeds c2, the error message "Cp ovfl" is issued to the console, program 
execution is abandoned and control returns immediately to CP/M.




Some examples of program fragments invoking C:

	""""C		Reads a REC program from the keyboard; the 
			compiled program starts at c1, the value of 
			c1 is left as top argument and the address 
			of the next available byte in the compiling 
			area is left as lower PDL argument. 

	"ABC""B"""C	Compiles the program contained in file 
			B:ABC.REC; the compiled program starts at c1 
			and the PDL is left with arguments as 
			described in the previous example.

	"FILENAMEEXT"
	"@"""C		Searches the currently logged disk for the 
			file FILENAME.EXT, to compile the REC program 
			it contains.  The result on the PDL is the 
			same as above.

	q""C		In this case, C is being directed to find the 
			source program between pointers p1 and p2 in 
			the workspace. 

	p""C		Analogous to the last example, but the source 
			is now on the PDL (and must be the argument 
			to which p is applied in this example).

	0""C		Replaces its arguments on the PDL with the
			values of c1 (as the lower argument) and
			c2-c1 (as the top).

	Operator C causes an error message "Rd ovfl" to be issued and 
execution to be terminated if the program being compiled contains syntax 
errors, which may be due to insufficient right parentheses or braces, lack of 
a main program in a subroutine group enclosed in braces or unbalanced 
quotation marks.  All of these circumstances cause an attempt to continue the 
compilation beyond the end of the file or memory area containing the source 
program, this is why they are grouped under the generic message "Rd ovfl".








	C can be used in combination with operator $ to compile programs 
contained in separate files, which can then be called as subroutines.  For 
instance, 

	('SUB1'"A"""C '1'$S m 'SUB2'"A" nC '2'$S 0$S;)

compiles the programs contained in files A:SUB1.REC and A:SUB2.REC.  The 
starting address (c1) of the first one is saved under subroutine name "1" 
['1'$S] and may be called by @1; the second program's starting address (which 
is the first following the first subroutine; note the use of m and n) is 
stored in the subroutine name table under the name "2", its execution is 
accomplished by the predicate @2.  Finally, the address of the next available 
byte in the compilation area is saved in variable 0 [0$S], foreseeing the 
possibility of compiling still another program without destroying subroutines 
1 and 2. A use of C which allows executing programs whose length exceed the 
size of the compilation area is that of overlay construction.  Consider the 
example in the following panel:






	{[compiles and executes the program whose source and
	  destination are on the PDL]
	 (C &0$S @@;) X

	 [main program: alternates executions of B:PROG1.REC 
	  and B:PROG2.REC, until either of them becomes false]
	 ("PROG1" 'B' ""@X "PROG2" 'B' ""@X:;)}

Subroutine X compiles the program whose source is indicated by the 
argument(s) it receives on the PDL, places the object in memory starting at 
c1 (when the top argument is the null string), stores the final address in 
variable 0 [&0$S] and executes the compiled program [@@]; the main program 
calls @X alternating executions of PROG1 and PROG2; the compilation of each 
of these programs overwrites the previous one's object program; PROG1 and 
PROG2 can communicate data through the PDL or the workspace.  Notice that 
PROG1 and PROG2 may in turn contain calls to X of the form 
"PROG3"'A'0$rpGm@Xn0$S, where the initial address for the object is now given 
by variable 0 and is the next available address in the compilation area, 
relative to the program containing the predicate @X, and the PDL complement 
is used to stack a copy of the current value of variable 0 (since it will be 
changed by subroutine X); this way overlay trees may be built.

:		Ch. 5, Part III. The OS Interface.

	We end this chapter with a discussion of the operators which provide 
the user with an interface to the operating system:

     Operator			Function performed

	_	(Underscore.)  Returns immediately to the OS.

	K	Calls the operating system to execute the function whose 
		number is given by the top PDL argument (which should be two 
		bytes long) with the lower argument copied to register DE (DX 
		on the 8086).  The lower argument remains on the PDL after K 
		is executed, and the top argument is replaced by the 
		resulting value of register A (AL on the 8086) extended to a 
		two-byte value by adjoining a zero upper byte; this value 
		usually indicates success or failure in the execution of the 
		BDOS function requested.

	k	Identical to K, but lifts both arguments and leaves no A value
		behind; it is mainly used to request functions for which it is
		not necessary to check the value of A returned by the BDOS.

	`	Predicate.  It is true if there is a character waiting to be 
		read from the console keyboard, false otherwise.  If true, 
		the character may be read by operator R.

	A warning on predicate `.  In MS-DOS, ctrl-S will suspend the 
execution of the program and ctrl-C will terminate it if either is the next 
character waiting to be read from the keyboard at the time ` is executed. An 
R following ` will NOT read either ctrl-S nor ctrl-C, because these are 
intercepted in the BIOS.  Thus a subroutine to check the keyboard status and 
suspend or terminate would take the following forms, for CP/M and MS-DOS, 
respectively:

	[keyboard check, CP/M]	((`);R3%=_;19%=RL;L;) K

	[keyboard check, MS-DOS]  (`;;) K

	3 and 19 are the ASCII codes for ctrl-C and ctrl-S, respectively;
% is used to restrict the values to one byte.  After ctrl-S suspends program
execution, typing any character will resume it.




	When the 8086 processor is used, the lower argument of K or k may be 
four bytes long, representing an address and a memory segment base; in this 
case the DS register value is saved, the segment base portion of the argument 
is transferred to DS, the function is executed and the previous value of DS 
is restored.  If the function requested is function number 26 (set DMA 
address), CP/M is called first to perform function 51 (set DMA segment base) 
with the segment base indicated by the lower argument (the data segment if 
this argument is two bytes long, the explicit base given if the length is 
four) and then the call to CP/M for function 26 is carried out.

	Not all CP/M functions require a value in DE (or DX); for those 
functions not needing it the PDL must still contain the corresponding 
two-byte argument in its place, 0 is recommended. 

	The use of operators K and k requires a thorough knowledge of the 
operation of CP/M function calls (for example, CP/M must be requested to open 
a file before reading from it, or to close a file used for writing in order 
to update the disk's directory and hence be able to access the data later, 
etc.), however, the discussion of all possible variants is beyond the scope 
of these notes, so we refer the reader to the bibliography given at the end.  
We limit ourselves here to giving a list of possible functions and 
illustrating the use of the more important ones.

	In the following table, applicable to CP/M, "Num" is the value which 
the top argument must have, "DE" is the kind of datum the lower argument 
should be and "Value" is the value K returns as top argument.  A dash in 
column "DE" indicates that the argument is not used (although both K and k 
require something in its place, usually a zero) and a dash in the "Value" 
column indicates that no specific value is returned in A (or AL) and hence 
the value left by K has no significance.

	As regards the abbreviations used in the table, "char" represents a 
character (to be written, if under "DE"; read if under "Value"), "FCB" 
represents the address of a file control block which can be created as shown 
in Chapter 3 or at the beginning of this chapter, "stat" indicates the datum 
contains a byte with the status referred to by the corresponding function, 
"buf" is the address of a buffer to be used for data transfer, "DMA" is the 
address of a 128-byte buffer to be used in operations to be subsequently 
performed on disk files, "id" is a disk identifier (0 for disk A, 1 for disk 
B, etc.) and "ind" means the returned value indicates the success or failure 
of the function.  The number 80 or 86 next to the function number means that 
line is applicable to the version of CP/M for the 8080 or 8086, respectively.




==========================CP/M BDOS functions========================
 Num			Function		 DE	       Value
=====================================================================
  0		System reset			 -		 -
  1		Read from console		 -		char
  2		Write to console		char		 -
  3		Read from reader		 -		char
  4		Write to punch			char		 -
  5		Write to printer		char		 -
  6 (80)	Read direct from console	255	     char or 0
  6 (80)	Write direct to console		char		 -
  6 (86)	Read direct from console	255		char
  6 (86)	Read console status		254		stat
  6 (86)	Write direct to console		char		 -
  7		Read I/O byte			 -		stat
  8		Write I/O byte			stat		 -
  9		Write string to console		buf		 -
 10		Read string from console	buf		 -
 11		Read console status		 -		stat
 12		Read version number		 -		ind
 13		Reset disk system		 -		 -
 14		Select disk			id		 -
 15		Open file			FCB		ind
 16		Close file			FCB		ind
 17		Search for first instance	FCB		ind
 18		Search for next instance	 -		ind
 19		Delete file			FCB		ind
 20		Read a sector sequentially	FCB		ind
 21		Write a sector sequentially	FCB		ind
 22		Make file			FCB		ind
 23		Rename file			FCB		ind
 24		Read logged disk vector		 -		stat
 25		Read logged in disk id		 -		id
 26		Set DMA address			DMA		 -
 28		Write protect disk		 -		 -
 30		Set file attributes		FCB		ind
 32		Get user code			255		ind
 32		Set user code		       0 to 15		 -
 33		Read random			FCB		ind
 34		Write random			FCB		ind
 35		Compute file size		FCB		 -
 36		Set random record		FCB		 -
 37 (86)	Reset selected disks		stat		 -
 40 (86)	Write random with zero fill	FCB		ind
 50 (86)	Direct BIOS call		buf		ind
=====================================================================
	Communication with MS-DOS is only slightly different:  more than two 
arguments may be required, depending on the function call and "n" is the 
MS-DOS function number.

	Each argument contains values for one or two registers; up to four 
registers may be assigned values. Since some functions require an argument in 
AL, this is taken from the HIGH order byte of "n".  For most functions the 
value returned ("code") is the value of AX.  Functions which will take two 
arguments from the PDL are 27H, 29H, 3CH, 3EH and all others above 3EH. 
Functions beyond 3EH not actually requiring the second argument will 
nevertheless lift an extra argument; loading an extra 0 will do.

	If a two byte argument XX is given where two registers R1:R2 are 
expected (R1 being the high order word), R1 will be assigned the value of DS 
and XX will be loaded into R2. With the exception of functions 2BH and 2DH, 
where arg1 is read as CX:DX, if arg1 is WW:XX and arg2 is YY:ZZ, XX will be 
loaded into DX and SI, ZZ will be loaded into BX and DI, YY (or DS if YY is 
absent) will be loaded into ES, and WW will be loaded into DS (unless WW is 
absent, in which case DS does not change) In the list below "fcb" and 
"buffer" represent the addresses of a file control block and a buffer, 
respectively. 


	Some functions return additional values besides AX. These are 
indicated in the list; each PDL argument produced by K is separated by a 
slash. Addr4 means a 4 byte address (seg:offset). An asterisk indicates that 
an extra value -1 (on error, in which case the remaining AX value is the 
error code) or an extra copy of AX (if no error) is returned.

=======================MS-DOS BDOS functions=========================
num	function			"arg1"	"arg2"	"code"
=====================================================================
0	program terminate		0	-	-
1	keyboard input			0	-	char
2	video output			char	-	AX
3	aux input			0	-	char
4	aux output			char	-	AX
5	printer output			char	-	AX
6	direct console I/O		DX	-	AX
7	dir console input, no echo	0	-	AX
8	console input, no echo		0	-	AX
9	print string			buffer	-	AX
10	buffered keyboard input		buffer	-	AX
11	keyboard status			0	-	stat
12	character input w/buffer flush	DX	-	AX

13	disk reset			0	-	AX
14	select disk			disk	-	AX
15	open file			fcb	-	code
16	close file			fcb	-	code
17	search once			fcb	-	code
18	search again			fcb	-	code
19	delete file			fcb	-	code
20	sequential read			fcb	-	code
21	write one record		fcb	-	code
22	create file			fcb	-	code
23	rename file			fcb	-	code
25	current disk			0	-	disk
26	set DMA address			dma	-	AX
27	allocation table address	not implemented
33	random read			fcb	-	code
34	random write			fcb	-	code
35	file size			fcb	-	code
36	set random record field		fcb	-	AX
37	set vector			addr	-	AX
38	create new program segment	seg	-	AX
39	random block read		fcb	CX	AX
40	random block write		fcb	CX	AX

41	parse file name			DS:SI	ES:DI	AX
42	get date			0	-	CX:DX/AX
43	set date			CX:DX	-	AX
44	get time			0	-	CX:DX/AX
45	set time			CX:DX	-	AX
46	set/reset verify flag		0	-	AX
47	get DMA address			0	-	addr4/AX
48	get DOS version No.		0	-	AX
49	terminate and stay resident	DX	-	-
51	ctrl-break check		DX	-	DX
53	get vector			0	-	addr4
54	get disk free space		disk	-  ax:cx/dx:bx/code
56	return country-dependent info	addr	-	AX/*
57	create subdirectory		addr	-	AX/*
58	remove directory entry		addr	-	AX/*
59	change current directory	addr	-	AX/*
60	create a file			addr	attrib	AX/*
61	open a file			addr	-	AX/*
62	close a file			0	handle	AX/*
63	read file/device		buffer	No:Hdl	AX/*
64	write file/device		buffer	No:Hdl	AX/*
65	delete file			addr	0	AX/*

66	move file pointer		DX	CX:Hdl	dx:ax/ax/*
67	change file mode		addr	0	CX/AX/*
68	IOCTL				0	handle	dx/ax/*
69	duplicate a handle		0	handle	AX/*
70	force duplicate of handle	0	CX:BX	AX/*
71	get current directory		disk	buffer	AX/*
72	allocate memory			0	BX	AX/*
73	free allocated memory		0	ES:0	AX/*
74	modify allocated mem blocks	0	ES:BX	BX/AX/*
75	load or execute a program	DS:DX	ES:BX	AX/*
76	terminate a process		0	0	-
77	get return code			0	0	AX/*
78	find first			addr	attrib	AX/*
79	find next			0	0	AX/*
84	get verify state		0	0	AX/*
86	rename a file			DS:DX	ES:DI	AX/*
87	get/set file date/time		DX	CX:BX	AX/*
=====================================================================





	As an example of K and k usage, assume FCBs have been created by 
means of subroutines M, C and F shown earlier in this chapter.  Then, the 
following subroutines can be used to open, close, make, read and write the 
files described by the FCBs.

	[set DMA buffer at absolute address 128]
	('080'H 26k;) h

	[delete file if present]
	(@h $r 19k;) g

	[open file or create it]
	(@h $r 15K (255= 22K 255= "Directory full"T_;;) LL;) e

	[open file or report absence]
	(@h $r 15K (255= ^11G T ": Not found"T_;;) LL;) f

	[open for reading file denoted by variable 30,
	 open for writing file denoted by variable 31]
	(30@f 31@g 31@e;) G



	[write 128  workspace bytes to the output file [var. 31],
	 false if less then 128 bytes in workspace]
	(Jj 26%EZD 0; 128a qL 26k 31$r
		21K(0= L;
		    1= "Directory full"T_;
		       "Disk full"T_)
		D'.'T;) p

	[write workspace from p0 to p1 to the output file]
	(jJ < (@p '.'=: 0=: L;) Zz>;) P

	[append a sector from the input file [var. 30], 
	 false when there is no more data to read]
	(128(e) "WS full"T_; qL 26k 30$r 20K 0=L; DLL) y

	[empty workspace to the output file, copying what is
	 left of the input file, and close the output file]
	(@p '.'=: L@y: (@p '.': 0=; e 26%(f:;) @p L; L;)
	 31 $r 16k;) H




	These subroutines could be a part of some program that reads from the 
input file to the workspace with @y and writes the processed data to the 
output file with @P; a call to subroutine H at the end would ensure that the 
output file is properly closed; the one byte value 26 [26%] used by H to fill 
the last sector of the output file is the ASCII character control-Z used by 
CP/M to signal the end of data in an ASCII text file.

	The above examples assume a CP/M model of file handling; CONVERT.REC 
and CNVLIB.REC for MS-DOS contain file-handling subroutines using the BDOS 
functions allowing for files in arbitrary subdirectories.

:[REC5.HLP]
[(c) G. Cisneros, 1985, 1990]
