How do you grab memory dynamically in CP/M?
I am trying to add an "INCLUDED" word to the Z80 hForth for CP/M. Now
INCLUDED nests, so the memory efficient way to handle that is to save
the information from a FCB to be able to get back to the next line
from a file that has just executed a word to include another file.
However, most straightforward is just to make a new FCB for the
included file, letting it run until its done, and then releasing it.
How is that normally done in CP/M? Do you just grab that kind of
memory from the hardware stack?
Unlike generic file I/O, this would be guaranteed to be nested.
Re: How do you grab memory dynamically in CP/M?
BruceMcF wrote:[color=blue]
> I am trying to add an "INCLUDED" word to the Z80 hForth for CP/M. Now
> INCLUDED nests, so the memory efficient way to handle that is to save
> the information from a FCB to be able to get back to the next line
> from a file that has just executed a word to include another file.
>
> However, most straightforward is just to make a new FCB for the
> included file, letting it run until its done, and then releasing it.
>
> How is that normally done in CP/M? Do you just grab that kind of
> memory from the hardware stack?
>
> Unlike generic file I/O, this would be guaranteed to be nested.[/color]
Can you use a recursive function to read the line? (Following example in C).
static char line[120]; /* Don't create for every new file */
void ProcessFile(char *name)
{
FILE *fp = fopen(name, "r");
while(fgets(line, sizeof(line) ,fp))
{
...
switch(Category(line))
{
case INCLUDE:
ProcessFile(newname);
break;
...
}
}
}
Re: How do you grab memory dynamically in CP/M?
On Thu, 3 Apr 2008 22:23:44 -0700 (PDT), BruceMcF
<agila61@netscape.net> wrote:
[color=blue]
>I am trying to add an "INCLUDED" word to the Z80 hForth for CP/M. Now
>INCLUDED nests, so the memory efficient way to handle that is to save
>the information from a FCB to be able to get back to the next line
>from a file that has just executed a word to include another file.
>
>However, most straightforward is just to make a new FCB for the
>included file, letting it run until its done, and then releasing it.[/color]
CP/M has no built in memory allocation scheme. It assumes a flat 64K
and there are few areas that are reserved for CP/M it self and all
other areas are fair game( can or may be over written).
However if the current progam is maintaing dicipline in how the TPA is
used then ayny scheme may be applied. If ther is memory management
available (paging or banking) then the doors open a bit wider to
create protected areas.
[color=blue]
>How is that normally done in CP/M? Do you just grab that kind of
>memory from the hardware stack?[/color]
No the stack is rarely that large and it's also potentially saved and
restored by bios and other software.[color=blue]
>
>Unlike generic file I/O, this would be guaranteed to be nested.[/color]
CP/M you have to be careful with file IO as it can be nested but
it is not safely recursive. It's a matter of the system being single
thread and not multitasking (unless MPM).
Allison
Re: How do you grab memory dynamically in CP/M?
On Apr 4, 4:59 am, David R Brooks <daveb...@iinet.net.au> wrote:[color=blue]
> Can you use a recursive function to read the line?[/color]
That is what I am writing, a recursive function to open a file, fetch
the characters in sequence from the file, then close it, where some of
those characters may resolve to a command that calls the same
function.
I can use that function ... once I've written it.
Re: How do you grab memory dynamically in CP/M?
On Apr 4, 7:42 am, no.s...@no.uce.bellatlantic.net wrote:[color=blue]
> CP/M has no built in memory allocation scheme. It assumes a flat 64K
> and there are few areas that are reserved for CP/M it self and all
> other areas are fair game( can or may be over written).[/color]
[color=blue]
> However if the current progam is maintaing dicipline in how the TPA is
> used then ayny scheme may be applied. If ther is memory management
> available (paging or banking) then the doors open a bit wider to
> create protected areas.[/color]
How do you find the end of the TPA? As far as I can see, hForth just
loads and starts growing in memory, basically assuming that there is
more there. Given that most TPA's will be in excess of 32K, and hForth
would be perfectly happy with a TPA of 16K, its a pretty safe
assumption, but how do I find the end of the TPA to start using RAM
from that side?
I don't need to create a protected area, I need to create a transitory
area. I have the Forth dictionary being built from the bottom to the
top:
[ defined words ... HERE ... ]
and I do not want to put the FCB and a block sector buffer in the
dictionary because then that will give:
[ defined words ... OLD-HERE FCB_0 ... FCB_n buff_0 ... buff_n
HERE ... ]
and if the application only needs INCLUDED and does not need the FILES
wordset, then that is memory taken away from the application that was
only needed to load the application definition file.
So what I want to design INCLUDED to do is:
[ ... HERE >>> ... <<< buff_0 ... buff_n FCB_0 ... FCB_n ]
.... where the top part is managed like a software file-access-stack,
with only a double variable in the codespace that points to the low
memory end of the file-access-stack and the top end of the file-access-
stack.
So INCLUDED would just adjust the bottom of the file-access-stack down
by the size of one FCB and one sector buffer, check that its above
HERE, set the end of codespace so that the dictionary cannot overflow,
starting feeding each character from each sector of the file in turn,
close the file when finished, re-adjust the pointer to the file-access-
stack up, if there is file-access data on the stack, pick up where it
left off, if the file-access stack is empty, return control to the
console.
[color=blue][color=green]
> >How is that normally done in CP/M? Do you just grab that kind of
> >memory from the hardware stack?[/color][/color]
[color=blue]
> No the stack is rarely that large and it's also potentially saved and
> restored by bios and other software.[/color]
[color=blue][color=green]
> >Unlike generic file I/O, this would be guaranteed to be nested.[/color][/color]
[color=blue]
> CP/M you have to be careful with file IO as it can be nested but
> it is not safely recursive. It's a matter of the system being single
> thread and not multitasking (unless MPM).[/color]
Only the foreground task would be able to use INCLUDED, background
tasks are restricted to using definitions that have already been
defined. So the INCLUDED file could define and launch a background
task, but that could not then execute INCLUDED.
That requires a few changes to the source of the multi-tasker, but the
multi-tasker is given in source (its one of the files that would be
INCLUDED), so that's not a big hurdle.
Re: How do you grab memory dynamically in CP/M?
On Apr 4, 10:58*am, BruceMcF <agil...@netscape.net> wrote:[color=blue]
> On Apr 4, 7:42 am, no.s...@no.uce.bellatlantic.net wrote:
>[color=green]
> > CP/M has no built in memory allocation scheme. *It assumes a flat 64K
> > and there are few areas that are reserved for CP/M it self and all
> > other areas are fair game( can or may be over written).
> > However if the current progam is maintaing dicipline in how the TPA is
> > used then ayny scheme may be applied. *If ther is memory management
> > available (paging or banking) then the doors open a bit wider to
> > create protected areas.[/color]
>
> How do you find the end of the TPA? As far as I can see, hForth just
> loads and starts growing in memory, basically assuming that there is
> more there. Given that most TPA's will be in excess of 32K, and hForth
> would be perfectly happy with a TPA of 16K, its a pretty safe
> assumption, but how do I find the end of the TPA to start using RAM
> from that side?
>[/color]
Let's see, it's been awhile,
jmp bdos, is jmp 0005h which holds another jmp instruction to the
BDOS base, which, in the typical cp/m memory map, is the top of TPA
+1+6. So location 0006h holds the address to TPA_top + 7, in that
TPA_top +1 thru 6 is the bdos s/n number. The bdos is page aligned,
nn00h, so the actual bdos entry is nn06h, nn00h..nn05H is the s/n, and
the 'page' byte of TPA_top is nn-1, and last addressable of TPA is
(nn-1)FFh. So, for an enviornment such as C, (nn-1)FFh could be the
top of the Program Stack. The area between program code|data and
program stack of stacksize is usually the Heap from which dynamic
memory is allocated.
Steve
[color=blue]
> I don't need to create a protected area, I need to create a transitory
> area. I have the Forth dictionary being built from the bottom to the
> top:
>
> [ defined words ... HERE ... ]
>
> and I do not want to put the FCB and a block sector buffer in the
> dictionary because then that will give:
>
> [ defined words ... OLD-HERE FCB_0 ... FCB_n buff_0 ... buff_n
> HERE ... ]
>
> and if the application only needs INCLUDED and does not need the FILES
> wordset, then that is memory taken away from the application that was
> only needed to load the application definition file.
>
> So what I want to design INCLUDED to do is:
>
> [ ... HERE >>> ... <<< buff_0 ... buff_n FCB_0 ... FCB_n ]
>
> ... where the top part is managed like a software file-access-stack,
> with only a double variable in the codespace that points to the low
> memory end of the file-access-stack and the top end of the file-access-
> stack.
>
> So INCLUDED would just adjust the bottom of the file-access-stack down
> by the size of one FCB and one sector buffer, check that its above
> HERE, set the end of codespace so that the dictionary cannot overflow,
> starting feeding each character from each sector of the file in turn,
> close the file when finished, re-adjust the pointer to the file-access-
> stack up, if there is file-access data on the stack, pick up where it
> left off, if the file-access stack is empty, return control to the
> console.
>[color=green][color=darkred]
> > >How is that normally done in CP/M? Do you just grab that kind of
> > >memory from the hardware stack?[/color]
> > No the stack is rarely that large and it's also potentially saved and
> > restored by bios and other software.[color=darkred]
> > >Unlike generic file I/O, this would be guaranteed to be nested.[/color]
> > CP/M you have to be careful with file IO as it can be nested but
> > it is not safely recursive. *It's a matter of the system being single
> > thread and not multitasking (unless MPM).[/color]
>
> Only the foreground task would be able to use INCLUDED, background
> tasks are restricted to using definitions that have already been
> defined. So the INCLUDED file could define and launch a background
> task, but that could not then execute INCLUDED.
>
> That requires a few changes to the source of the multi-tasker, but the
> multi-tasker is given in source (its one of the files that would be
> INCLUDED), so that's not a big hurdle.[/color]
Re: How do you grab memory dynamically in CP/M?
"BruceMcF" <agila61@netscape.net> wrote in message
news:81b30d4f-7f84-480a-ab00-3aa8a3cd8117@k13g2000hse.googlegroups.com...[color=blue]
> How do you find the end of the TPA?[/color]
I haven't been following this in detail, but I gather we're talking about
CP/M-80 here. If so...
Take the word (16 bits) stored at locations 0x0006 and subtract one.
See page 6-26 at [url]http://www.cpm.z80.de/manuals/cpm22-m.pdf[/url] reading the note
about 0005H - 0007H.
- Bill
Re: How do you grab memory dynamically in CP/M?
BruceMcF wrote:[color=blue]
>[/color]
.... snip ...[color=blue]
>
> How do you find the end of the TPA? As far as I can see, hForth
> just loads and starts growing in memory, basically assuming that
> there is more there. Given that most TPA's will be in excess of
> 32K, and hForth would be perfectly happy with a TPA of 16K, its
> a pretty safe assumption, but how do I find the end of the TPA
> to start using RAM from that side?[/color]
Address 5 contains a <jmp bdos> instruction. The operand of that
instruction ends in '06' (hex) and the whole address is the lowest
address of the BDOS module. The 6 bytes below it CAN (but usually
don't) contain a serial number. Below that address is the CCP,
which is not needed when running a program, and which is reloaded
on a reboot.
So that address, which can be found by loading the 16 bit value
found at address 0006, gives the first address that must not be
disturbed to preserve BDOS. You can use everything below it,
bearing in mind the reserved usage for the area below 0100h.
If you don't need the bdos during program run you can find the
bottom of the bios via the pointer at address 0001. This is used
in rebooting by a jump to 0.
Things are different when such things as DDT or DDTZ are in use.
Also system extensions.
I recommend getting and reading the source code for a clone of
CP/M. One that is available is DOSPLUS 2.5, both as binaries and
as source, available at:
<http://cbfalconer.home.att.net/download/cpm/>
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
--
Posted via a free Usenet account from [url]http://www.teranews.com[/url]
Re: How do you grab memory dynamically in CP/M?
On Apr 4, 3:51 pm, "Bill Leary" <Bill_Le...@msn.com> wrote:[color=blue]
> "BruceMcF" <agil...@netscape.net> wrote in message
>
> news:81b30d4f-7f84-480a-ab00-3aa8a3cd8117@k13g2000hse.googlegroups.com...
>[color=green]
> > How do you find the end of the TPA?[/color]
>
> I haven't been following this in detail, but I gather we're talking about
> CP/M-80 here. If so...
>
> Take the word (16 bits) stored at locations 0x0006 and subtract one.
>
> See page 6-26 athttp://www.cpm.z80.de/manuals/cpm22-m.pdfreading the note
> about 0005H - 0007H.
>
> - Bill[/color]
Thanks, that's easy to do.
: TPA ( -- &tpa ) 6 @ 1- ;
.... and thanks for the link.
Re: How do you grab memory dynamically in CP/M?
On Apr 4, 6:33 pm, CBFalconer <cbfalco...@yahoo.com> wrote:[color=blue]
> I recommend getting and reading the source code for a clone of
> CP/M. One that is available is DOSPLUS 2.5, both as binaries and
> as source, available at:[/color]
After looking at the Z-system that is running under the hood of MyZ80,
and the ability to load temporary extensions below the CCP, and the
ability to have "load high" environment-3 programs, I think I'll just
set the top of RAM for the extended-hforth at $7FFF and leave $8000 on
up to the system. After all, 20K codespace is ample for any minimalist
Forth, leaving 31.75K - codespace for RAM allocated dynamically by
hforthx.
Then its just documentation ... "HFORTHX.COM requires a 31.75K TPA".
Re: How do you grab memory dynamically in CP/M?
On Apr 5, 11:09 am, BruceMcF <agil...@netscape.net> wrote:[color=blue]
> On Apr 4, 6:33 pm, CBFalconer <cbfalco...@yahoo.com> wrote:
>[color=green]
> > I recommend getting and reading the source code for a clone of
> > CP/M. One that is available is DOSPLUS 2.5, both as binaries and
> > as source, available at:[/color]
>
> After looking at the Z-system that is running under the hood of MyZ80,
> and the ability to load temporary extensions below the CCP, and the
> ability to have "load high" environment-3 programs, I think I'll just
> set the top of RAM for the extended-hforth at $7FFF and leave $8000 on
> up to the system. After all, 20K codespace is ample for any minimalist
> Forth, leaving 31.75K - codespace for RAM allocated dynamically by
> hforthx.[/color]
[color=blue]
> Then its just documentation ... "HFORTHX.COM requires a 31.75K TPA".[/color]
On second thought, after saving the hforthx.com with the SEARCH-ORDER
core and TOOLS core ``SEE DEBUG .S MARKER'' etc., and mostly without
extensions, its already 16K. So make that a 40K TPA.
I'm getting the impression that the most common target model for
hForth in DOS is the EXE model.
Re: How do you grab memory dynamically in CP/M?
On Tue, 8 Apr 2008 11:36:34 -0700 (PDT), BruceMcF
<agila61@netscape.net> wrote:
[color=blue]
>On Apr 5, 11:09 am, BruceMcF <agil...@netscape.net> wrote:[color=green]
>> On Apr 4, 6:33 pm, CBFalconer <cbfalco...@yahoo.com> wrote:
>>[color=darkred]
>> > I recommend getting and reading the source code for a clone of
>> > CP/M. One that is available is DOSPLUS 2.5, both as binaries and
>> > as source, available at:[/color]
>>
>> After looking at the Z-system that is running under the hood of MyZ80,
>> and the ability to load temporary extensions below the CCP, and the
>> ability to have "load high" environment-3 programs, I think I'll just
>> set the top of RAM for the extended-hforth at $7FFF and leave $8000 on
>> up to the system. After all, 20K codespace is ample for any minimalist
>> Forth, leaving 31.75K - codespace for RAM allocated dynamically by
>> hforthx.[/color]
>[color=green]
>> Then its just documentation ... "HFORTHX.COM requires a 31.75K TPA".[/color]
>
>On second thought, after saving the hforthx.com with the SEARCH-ORDER
>core and TOOLS core ``SEE DEBUG .S MARKER'' etc., and mostly without
>extensions, its already 16K. So make that a 40K TPA.
>
>I'm getting the impression that the most common target model for
>hForth in DOS is the EXE model.[/color]
Here is a trick I've used to create CP/M protected space. Put what
every code you want to be out of the TPA above the BIOS. That
translates to building a CP/M system that is smaller by whatever space
you want out of the TPA. In my Case I generally do 1/2/4K
(0F[0,8,C]00->FFFFh) as reserved space and move wevery thing down that
amount. A system with 4k reserved that way will generally have a TPA
of 54-56K wich by CP/M standards is very good and if you have the BDOS
resident that only takes 3.5K off that (50.5-52.5k). That would allow
a fairly great amount of space and the location 6/7 data minus 6 will
be the usual TPA space. Typical TPAs for decent systems is at least
48K(0C000h).
Allison
Re: How do you grab memory dynamically in CP/M?
On Apr 8, 6:25 pm, no.s...@no.uce.bellatlantic.net wrote:[color=blue]
> Here is a trick I've used to create CP/M protected space.[/color]
Thanks for that ... the information is filed for when I need it. This
particular step doesn't need protected space ... I'm more concerned
about protecting other things from this. But after looking around the
conventional CP/M, I figure if a 40K TPA is on the low side, then
it'll have the programs with larger TPA's running interference, as it
were.
Further, this is not hard to modify ... once its working,
HEX C000 TO ram-end save# BYE
.... will give, if there are 58 pages in codespace:
HEX C000 TO ram-end save# BYE 56 ok
then
A2>save 56 hforthx.com
.... and the new hforthx.com image will operate on the presumption of a
48K TPA ...
HEX 8000 TO ram-end
.... and the image will assume it has a 32K TPA.
What's great about CP/M was the only thing I to get a SAVE-SYSTEM
function in a minimalist Forth was the little routine to print out the
codespace size in pages, and that was adapted from Brad Rodriguez's
instructions for getting the page parameter for the Z80 CamelForth.
I've done a trial run in extending hForth by hand, entering the most
essential functions ("words") from OPTIONAL.F by hand and
incrementally saving hforth1.com, hforth2.com, etc. up to the the
hforthx.com with the main debugging tools (DUMP SEE .S MARKER) ...
.... that seems to be working. DUMP was an awfully long routine for
Forth, with next to no factoring, and I bailed out the first time I
was typing it in, but I was surprised to see that when I had a
definition that compiled, it seemed to work perfectly.
So I'll be working with that hForthx.com with the embedded debugging
routines to develop the routines that can INCLUDE files, and then go
back to the original hforth.com and built the capability into that.
Then hforth.com will be able to load files from text source (including
file based definitions of the stuff I hand-coded into hforthx.com),
and I can move up to using VDE for working on hForth source within CP/
M.
Re: How do you grab memory dynamically in CP/M?
/*
Full K&R alloc() and free() for AZTEC C II
This module adapted for the CP/M environment from source code in Brian
W. Kernighan and Dennis M. Ritchie's "The C Programming Language" by
William C. Colley III -- 4 OCT 1982.
This module implements the functions alloc(), morecore(), sbrk(), and
free() as per pp. 173-7 of Kernighan and Ritchie. Since sbrk() is
responsible for preventing collision between the allocated data and
the stack, it must know how much space to leave for the stack. Thus,
a function rsvstk() is provided to override the default 1024 bytes.
The functions in this package are:
char *alloc(nb) Allocates a block of nb bytes and
unsigned nb; returns a pointer to it. If no such
block is available, the value NULL (0)
is returned.
free(blk) Attaches the storage allocation block
char *blk; blk to the free list. Returns no
meaningful value.
HEADER *morecore(nb) Gets a storage allocation block of
unsigned nb; size nb from the heap and returns a
pointer to it. Returns NULL (0) if
not enough space is available.
char *sbrk(nb) Gets nb bytes from the heap. Returns
unsigned nb; a pointer to the bytes or -1 if not
enough bytes are available.
char *settop(nb) Gets nb bytes from the heap. Returns
unsigned nb; a pointer to the bytes or NULL (0) if
not enough bytes are available.
rsvstk(stk) Changes the minimum allowable remaining
unsigned stk; stack size at a call to sbrk() to stk
bytes. Default value is 1024 bytes.
*/
#define NULL 0
union header {
struct {
union header *ptr;
unsigned size;
} s;
long l;
};
typedef union header HEADER;
static HEADER base, *allocp = NULL;
char *alloc(nb)
unsigned nb;
{
HEADER *morecore();
register HEADER *p, *q;
register unsigned nu;
nu = ((nb + 3) >> 2) + 1;
if ((q = allocp) == NULL) {
base.s.ptr = allocp = q = &base;
base.s.size = 1;
}
for (p = q->s.ptr; ; q = p, p = p->s.ptr) {
if (p->s.size >= nu) {
if (p->s.size == nu) q->s.ptr = p->s.ptr;
else {
p->s.size -= nu;
p += p->s.size;
p->s.size = nu;
}
allocp = q; return (char *)(p + 1);
}
if (p == allocp)
if ((p = morecore(nu)) == NULL) return NULL;
}
}
HEADER *morecore(nu)
unsigned nu;
{
char *sbrk();
register char *cp;
register HEADER *up;
if ((int)(cp = sbrk(nu << 2)) == -1) return NULL;
up = (HEADER *)cp;
up->s.size = nu;
free((char *)(up + 1));
return allocp;
}
free(blk)
char *blk;
{
register HEADER *p, *q;
p = (HEADER *)blk - 1;
for (q = allocp; !(p > q && p < q->s.ptr); q = q->s.ptr)
if (q >= q ->s.ptr && (p > q || p < q->s.ptr)) break;
if (p + p->s.size == q->s.ptr) {
p->s.size += q->s.ptr->s.size;
p->s.ptr = q->s.ptr->s.ptr;
}
else p->s.ptr = q->s.ptr;
if (q + q->s.size == p) {
q->s.size += p->s.size;
q->s.ptr = p->s.ptr;
}
else q->s.ptr = p;
allocp = q;
}
/* The functions sbrk(), settop(), and rsvstk() live in the module
sbrk.mac
as they have to beat on machine things like the stack pointer. */
x--- snip ---x
;
; Rest of Full K&R alloc() and free() for AZTEC C II
;
; This module copyright (c) 1982 William C. Colley III
;
; I grant Manx Software Systems permission to incorporate these
functions
; into the AZTEC C library subject only to the condition that my
copyright
; notice remain in the source code. WCC3.
;
; See the module ALLOC.C for documentation. To use this module, you
must
; modify the AZTEC module CALLCPM.ASM by removing the definition of
the
; location $MEMRY. You also will save code if you remove their
function
; settop()/sbrk() as two of these functions will replace it.
;
PUBLIC settop_, sbrk_, rsvstk_, $MEMRY
CSEG
;******************************************************************************
settop_: LXI H, 4 ;Fudge up a call to sbrk() to allocate
CALL sbrk1 ; the space.
INX H ;If sbrk() returned -1, set the Z flag
MOV A, H ; and return 0 as space was not
ORA L ; available.
RZ
DCX H ;If space was available, return a
RET ; pointer to the space. Note that
; Z flag is cleared at this point.
sbrk_: LXI H, 2 ;Get size of block to allocate and
sbrk1: DAD SP ; compute end address of prospective
MOV E, M ; block.
INX H
MOV D, M
LHLD $MEMRY
DAD D
XCHG
JC sbrk2 ;If block wraps around top of memory,
; not enough space available.
LHLD safety ;Compute stack pointer less safety
DAD SP ; margin -- i.e. top of memory.
MOV A, L ;If end address > top of memory,
SUB E ; not enough space available.
MOV A, H
SBB D
JC sbrk2
LHLD $MEMRY ;If space is available, allocate
XCHG ; the space, set Z flag on pointer,
SHLD $MEMRY ; and return pointer to space.
XCHG
MOV A, H
ORA L
RET
sbrk2: XRA A ;If not enough space, clear the Z flag
DCR A ; and send back -1.
MOV H, A
MOV L, A
RET
;******************************************************************************
rsvstk_: LXI H, 2 ;Get new stack safety margin.
DAD SP
MOV A, M
INX H
MOV H, M
CMA ;Negate and save it.
MOV L, A
MOV A, H
CMA
MOV H, A
INX H
SHLD safety
RET ;Return nothing in particular.
;******************************************************************************
DSEG
$MEMRY: DW 0 ;Let linker put end of externals here.
safety: DW -1024 ;Default value of safety margin.
END
Re: How do you grab memory dynamically in CP/M?
On Apr 9, 7:06 am, Bill Buckels <bbuck...@escape.ca> wrote:
.... a bunch of C routines ...
hForth is Forth. If I implement ALLOCATE and FREE for hForth it will
be:
(1) in Forth and
(2) much smaller than that
There is already a Forth-94 wordset that defines a dataspace buffer in
the dictionary and the heap memory wordset to work with it, so if I
decide to do it, its not like I have to write the whole system from
scratch.
The only question is whether I decide to do it, since the FCB and file
sector buffers for INCLUDE are so well suited to a pure (software)
stack.
Re: How do you grab memory dynamically in CP/M?
I just put the CP/M hforth that I expanded on the console to include a
selection of the OPTIONAL.F words here:
[url]http://groups.google.com/group/niclos-for-forth-94/web/hforthx-for-console-development[/url]
Re: How do you grab memory dynamically in CP/M?
On Apr 4, 1:29 pm, s_dubrov...@yahoo.com wrote:[color=blue]
> Let's see, it's been awhile,
> jmp bdos, is jmp 0005h which holds another jmp instruction to the
> BDOS base, which, in the typical cp/m memory map, is the top of TPA
> +1+6. So location 0006h holds the address to TPA_top + 7, in that
> TPA_top +1 thru 6 is the bdos s/n number. The bdos is page aligned,
> nn00h, so the actual bdos entry is nn06h, nn00h..nn05H is the s/n, and
> the 'page' byte of TPA_top is nn-1, and last addressable of TPA is
> (nn-1)FFh. So, for an enviornment such as C, (nn-1)FFh could be the
> top of the Program Stack. The area between program code|data and
> program stack of stacksize is usually the Heap from which dynamic
> memory is allocated.
>
> Steve[/color]
Thanks, this is what it turns out I needed to understand what CP/M
hForth was doing.
What I thought was an issue is no an issue after all, hForth grabs the
top of the TPA for its text input buffer and PAD at the start, so I
just say:
``PAD cell-''
and I am in the free RAM I was looking for.
After my rummaging around to figure it out, I've decided to just go
ahead and define an ALLOCATE FREE and RESIZE that use that memory, and
then use those functions for the INCLUDED routine. That will give more
leverage to someone trying to bootstrap something up in hForth for CP/
M.
All of this hopefully finished in time, for when I have the funds in
hand for either a C128 or PX-8, or preferably both.
CP/M hforthm.cpm uploaded (Was Re: How do you grab memory dynamicallyin CP/M?)
On Apr 4, 1:23 am, BruceMcF <agil...@netscape.net> wrote:[color=blue]
> I am trying to add an "INCLUDED" word to the Z80 hForth for CP/M. Now
> INCLUDED nests, so the memory efficient way to handle that is to save
> the information from a FCB to be able to get back to the next line
> from a file that has just executed a word to include another file.
>
> However, most straightforward is just to make a new FCB for the
> included file, letting it run until its done, and then releasing it.
>
> How is that normally done in CP/M? Do you just grab that kind of
> memory from the hardware stack?
>
> Unlike generic file I/O, this would be guaranteed to be nested.[/color]
The google group page ...
[url]http://groups.google.com/group/niclos-for-forth-94/web/hforthx-for-console-development[/url]
.... has some details on hforthm.cpm which is a CP/M .COM file
containing CP/M hForth, extended to include the programming tools
wordset and memory allocation wordset.
The ALLOCATE and FREE are very simple-minded, since there's no need to
be sophisticated to support INCLUDED.
It goes without saying ... therefore probably ought to be said ...
rename hforthm.cpm to hforthm.com ... Google Groups as such is happy
to host files, but not .COM files.