A friend recently claimed that "DEC B; RET", was a valid 2-byte CP/M
executable program for a Z80 machine. I believe that's true. And when
viewed left-to-right in radix-256 notation. < 5, 201 > = 1481, it is a
prime number.
I conjectured that on another Z80 based OS, that "INC B, RST 08" would
represent a smaller valued prime number. However, the OS in question (ZX
Spectrum), the program is only arguably a valid executable, as it causes
the spectrum to reset.
I'm not aware of whether there is any significance to any of the RST
instructions in Z80 implementations of CP/M. Are they used as OS traps
at all? I.e. can they be used to exit a program cleanly (or to reset the
machine). (Vendor-specific extensions would be fine too.)
Cheers,
Phil
Okay!, I'll try to be! :-)
> A friend recently claimed that "DEC B; RET", was a valid 2-byte CP/M
> executable program for a Z80 machine. I believe that's true. And when
> viewed left-to-right in radix-256 notation. < 5, 201 > = 1481, it is a
> prime number.
Well, all "DEC B; RET" would be doing is decreasing the value in B &
exiting the program (or RETurning from where it came from).
> I conjectured that on another Z80 based OS, that "INC B, RST 08" would
> represent a smaller valued prime number. However, the OS in question (ZX
> Spectrum), the program is only arguably a valid executable, as it causes
> the spectrum to reset.
I may not be right be, but my knowledge of the "RST" instruction makes me
think it's been designed as a way of doing something only more compact.
From my notes for an "Amstrad CPC" based computer an "RST 6" is designed
like this. The example is a Jump example (between addresses) & the "RST 6"
acts as a Jump instruction. A actual jump instruction would use 3 or 4?
Bytes for this instruction yet this instruction when setup to do somthing
like this takes up less memory, so there's more memory for a programmer to
use.
> I'm not aware of whether there is any significance to any of the RST
> instructions in Z80 implementations of CP/M. Are they used as OS traps
> at all? I.e. can they be used to exit a program cleanly (or to reset the
> machine). (Vendor-specific extensions would be fine too.)
The "RST" isn't used to exit a program cleanly. The "RET" does this & it
only uses one byte "C9" to exit a program cleanly. However "RET" is also
used at the end of a function & when used with a "CALL" statement
it RETurns back to the spot in memory after that "CALL", so it doesn't
always End a program.
On an Amstrad (which is nearly like a Spectrum in terms of Assembly)
there is an instruction which resets the computer in the form of "RST 0"
this is the statement which resets the computer totally.
Unfortunately, I don't have any real knowledge of what "RST 8" does on a
Spectrum so it could be very possible that my "RST" instructions could
have a different meaning on what they do. Sorry.
Ross.
In the eight-bit CP/M
world, its use is pretty
much limited to debuggers
like DDT aside from RST 0,
which is the shortest
possible code to execute
a warm boot program exit
and reload of the CCP
(and, in a few systems
like Kaypros, the BDOS).
Since a warm boot routine
re-establishes the CCP
stack before jumping to
the CCP entry point, an
RST 0 (or CALL 0)
instruction has the same
effect as the more
conventional JMP 0 --
it branches to the BIOS
warm boot vector.
> Phil Carmody <fatphil_did...@altavista.com> wrote in
> message news:<3C221395...@altavista.com>...
>
>> A friend recently claimed that "DEC B; RET", was a valid 2-byte CP/M
>> executable program for a Z80 machine. I believe that's true. And when
>> viewed left-to-right in radix-256 notation. < 5, 201 > = 1481, it is a
>> prime number.
>
> Well, all "DEC B; RET" would be doing is decreasing the value in B &
> exiting the program (or RETurning from where it came from).
RET pops the top of the stack into the program counter, so "DEC B; RET"
is valid but not guaranteed to exit. Anything could be on the stack.
"RST n" are single byte instructions. Push a return address on the
stack, execute a CALL to address 8*n. Hardware interrupts can make
use of these one-byte instructions.
Gee, and I thought I might never open Alan Miller's "8080/Z80 Assembly
Language -- Techniques for improved programming" again. :-)
--
Mike Spencer Nova Scotia, Canada
No, the CCP does a "call" to the program, not a "jump", so a RET
is a perfectly valid way to exit.
-- Dave Tweed
and many programs did. That was a bug in the original DDT, in
that that RET couldn't find any reasonable place to go. IIRC I
fixed it in DDTZ.
--
Chuck F (cbfal...@yahoo.com) (cbfal...@XXXXworldnet.att.net)
Available for consulting/temporary embedded and systems.
(Remove "XXXX" from reply address. yahoo works unmodified)
mailto:u...@ftc.gov (for spambots to harvest)
> -- Dave Tweed
This is correct so long as everything that the current program put on
the stack has been removed. It would not work if something like these
were the last instructions in the executing program:
push hl
ret
[unless, of course, the content of HL happened, by pure chance, to be
the return address].
The following would also likely crash the OS if they were the last
two instructions in the executing program (assuming the SP has the
same value it had when just after the OS CALLed the program):
pop hl
ret
--
Nemo esse vult nemo
et quoniam nemo sum ego,
is ipse sum qui esse volo!
--Terry Groff (translation into Latin by ne...@nunc.invalid)
Sorry if this sounds like I'm going round in circles but I want to be
quite clear before I present my findings to a third party. For example,
I don't know what 'CCP' means, but it seems not to matter too much. My
interpretation of the above, and the several other comments is that:
The single byte program "RST 00", represented as a single byte file
"0xC7", is a valid "warm-reboot" program under CP/M.
True/False/debatable?
If true, I'm a happy man, I shall go update my web-page, and give a big
thank you to you guys.
If not, then I'll require more thought.
Phil
CCP means the console command program, equivalant to a Unix shell
or MsDos Command.com or 4dos.com (if you are using a more
reasonable MsDos shell).
> The single byte program "RST 00", represented as a single byte file
> "0xC7", is a valid "warm-reboot" program under CP/M.
>
> True/False/debatable?
>
> If true, I'm a happy man, I shall go update my web-page, and give
> a big thank you to you guys.
> If not, then I'll require more thought.
For any semi-normal CP/M, yes. The Trash80's Model 3 had a
non-standard implementation that started elsewhere, and can
probably be ignored. You can also use JMP 0 and CALL 0.
Notice that the 2 byte operand at 1 pointed to a memory area that
should not be altered by any program. Similarly the 2 byte
operand at 5 pointed to the area that should not be altered by any
program using the CP/M system proper. (Both rounded down to a
multiple of 128(dec) bytes). Similarly anything below location
0x4c (IIRC) shouldn't be touched without knowing *exactly* what
you are doing on *your* system.
"CBFalconer" <cbfal...@yahoo.com> wrote in message
news:3C238643...@yahoo.com...
> Dave Tweed <dtw...@acm.org> wrote:
> > Mike Spencer wrote:
> >> RET pops the top of the stack into the program counter, so "DEC B; RET"
> >> is valid but not guaranteed to exit. Anything could be on the stack.
That's assuming if there is anything on the stack, that statement doesn't
suggest that.
> > No, the CCP does a "call" to the program, not a "jump", so a RET
> > is a perfectly valid way to exit.
>
> > -- Dave Tweed
>
> This is correct so long as everything that the current program put on
> the stack has been removed. It would not work if something like these
> were the last instructions in the executing program:
>
> push hl
> ret
>
> [unless, of course, the content of HL happened, by pure chance, to be
> the return address].
>
> The following would also likely crash the OS if they were the last
> two instructions in the executing program (assuming the SP has the
> same value it had when just after the OS CALLed the program):
>
> pop hl
> ret
My point I was trying to make is in the past I've used the 'RET' statement
as a valid way of exiting my Z80 programs & occasionally I would use it in a
subprogram which is 'call'ed by another section of the program to finish it.
Even my experience with Z80 at college has taught me that the 'RET' is a way
of exiting a program. I have not had much experience with using 'push' or
'pop' but what I do know now is if somthing is 'push'ed onto the stack then
it has to be 'pop'ed before such an program can finish.
Ross.
. .
|
\_/
You are correct.
> The single byte program "RST 00", represented as a single byte file
> "0xC7", is a valid "warm-reboot" program under CP/M.
>
> True/False/debatable?
This should be true under any version of CP/M which follows the
convention that address 00H holds a JMP instruction to the CP/M
warmboot address. So it's debatable only to the extent that some
implementations of CP/M may have violated the convention, e.g.,
Chuck F> The Trash80's Model 3 had a non-standard implementation that
Chuck F> started elsewhere...
Would be true on Osborne 1, the only CP/M system I know much about.
> In article <3C238643...@yahoo.com>,
> CBFalconer <cbfal...@worldnet.att.net> wrote:
>
> > Phil Carmody wrote:
> >
> ..............
> >> I don't know what 'CCP' means, but it seems not to matter too much.
> ..............
> > CCP means the console command program,
> ..............
>
> Doesn't CCP mean "Console Command Processor" ? That's what my CP/M
> documentation says at least. And remember that it's part of the CP/M
> OS, not a CP/M application like PIP and friends.
It roughly corresponds to the DOS command.com. As I recall, when you type
a command like "pip" the ccp is what "calls" PIP, and then after the job
is finished, ccp is reloaded.
Roy
RST 8 (on a Spectrum) means "print a BASIC error message and pass control
to the BASIC interpreter". It is followed by a one-byte inline parameter
that says which message to print, eg:
RST 8 ;in 8080, this would be written RST 1
DEFB 0FFh ;"OK"
RST 8
DEFB 0 ;"NEXT without FOR"
To see all the messages, type the following program into a Spectrum or
Spectrum emulator:
10 FOR n=0 TO 255: POKE 23610,n
Then run it, and type NEXT n at each error message that appears.
The Spectrum BASIC ROM also uses RST 0 (reboot), RST 10h (Write character
in A to current output device). The other RSTs are used, but mainly
internally by the syntax checker; though I think RST 28h is used to get at
the floating-point library.
--
------------- http://www.seasip.demon.co.uk/index.html --------------------
John Elliott |BLOODNOK: "But why have you got such a long face?"
|SEAGOON: "Heavy dentures, Sir!" - The Goon Show
:-------------------------------------------------------------------------)
Walter Rottenkolber
> The CCP (command control processor) is the default program module in CPM
> that puts the A prompt on the screen and reads your input commands. Small
> programs that don't overwrite the CCP can do a simple final RET to return
> you to the CCP. To get extra space, the program can overwrite CCP, but then
> the program has to do a warm boot on exit to ensure that the CCP is
> reloaded.
> Walter Rottenkolber
IIRC, the CCP in pre-CP/M 3 implementations resided in high memory
just "under" the BDOS. In CP/M 3 (aka CP/M Plus), the CCP was loaded
at 0100 just like other programs. CP/M3 would also allow the
permanent loading of the CCP into "banked" memory from which it could
be loaded into 0100 extremely fast with a memory-to-memory copy. In
that case, a warm boot seemed to occur instanteously.
It was quite possible to write a resident RSX in CP/M 2.2 (tsr to
msdosians) which locked in the CCP, protected memory, and provided
that effect at all times. It cost the size of the CCP plus 128
bytes of memory availability.
Ah, okay. I don't know if that applys on an Amstrad CPC computer, however I
do know there was a way of doing it via a 'firmware' call. Of course the
only difference between that & a RST 8 is the amount in bytes (memory) it
would use. The Amstrad also has a built-in command in BASIC (simply called
'ERROR') which used a value to generate a Error message. I suppose that
would tie in with what the 'RST 8' does.
Just another quick note to follow up something I said earlier about exiting
a program (by issuing a 'RET' statement). I've had a look at an Assembly
example from a book which is a CP/M program, in their example they have
issued a 'JP 0' which in their case returns to CP/M. To my knowledge a
command such as 'JP 0' on an Amstrad would exit CP/M & reboot the BASIC
from the ROM. So in all view I think a command such as 'JP 0' would vary
from One machine to another (depending on how CP/M is managed on that
machine).
Ross.
. .
|
\_/
Ross Simpson wrote:
>
> Just another quick note to follow up something I said earlier about exiting
> a program (by issuing a 'RET' statement). I've had a look at an Assembly
> example from a book which is a CP/M program, in their example they have
> issued a 'JP 0' which in their case returns to CP/M. To my knowledge a
> command such as 'JP 0' on an Amstrad would exit CP/M & reboot the BASIC
> from the ROM. So in all view I think a command such as 'JP 0' would vary
> from One machine to another (depending on how CP/M is managed on that
> machine).
Address 0000h on the z80/8080/8085 chips is the cold start address.
When you power up the microprocessor and reset it (usually done at the
same time with a power on reset circuit) the chip will load 0000h into
the program counter and begin execution there.
This means that to start these machines, there has to be ROM mapped
into the memory map at 0000h or special hardware to force a jump
instruction followed by an address to a ROM, or some other trick to gain
control of the microprocessor.
On machines like the TRS-80 Model III, ROM is permanently mapped into
low memory starting at 0000h, and a jump or rst0 to that location will
reset the machine as if you turned the power off and then back on again.
On machines that had RAM throughout the memory map, a ROM was usually
phantomed (switched in) to bootstrap the machine and then switched out
once the machine was up and running from the RAM. In that case,
software can modify the contents of memory at 0000h and alter the
behavior of the machine on jump 0000h or rst0 or, on some machines, the
reset switch.
This is what CP/M does. On cold start the entire system is loaded.
Once loaded, the vector at 0000h is altered to point to the CP/M BIOS
warm start routine and hence transferring program control to that
address results in a warm start. (loading of BDOS and CCP, but
generally not BIOS. Some reset the IO byte, some do not.)
-Frank
True except for certain non-
standard CP/M 80
implementations. If "RST 0"
doesn't work in a particular
CP/M implementation, neither
will "JMP 0" or "CALL 0."
>
>If true, I'm a happy man, I shall go update my web-page, and give a big
>thank you to you guys.
>If not, then I'll require more thought.
>
No further "thought"
required, Phil. Happy
holidays to you!
I guess I've never lost the Zilog mindset: starting ROM at 0 seems quite natural
since the "PC" locating things at the "top" of memory created holes in the RAM,
thus artificial low ram/extended/expanded/hi-ram, the "640 k limit", etc.
> This means that to start these machines, there has to be ROM mapped
>into the memory map at 0000h or special hardware to force a jump
>instruction followed by an address to a ROM, or some other trick to gain
>control of the microprocessor.
Ah, all the wonderful exploration of memory management with
small address spaces. I was sooooo tempted to make my own Z80 MMU
using the M1 line for DEC-style separate instruction and data address spaces.
> On machines like the TRS-80 Model III, ROM is permanently mapped into
>low memory starting at 0000h, and a jump or rst0 to that location will
>reset the machine as if you turned the power off and then back on again.
>
> On machines that had RAM throughout the memory map, a ROM was usually
>phantomed (switched in) to bootstrap the machine and then switched out
>once the machine was up and running from the RAM. In that case,
>software can modify the contents of memory at 0000h and alter the
>behavior of the machine on jump 0000h or rst0 or, on some machines, the
>reset switch.
There were several ways to accomplish that.
The cheap way: bank switch the memory around
with the ROM being enabled/disabled at low addresses.
I remember one machine with hardware that copied the ROM to RAM upon power-on
since the ROM was too slow to run direct, RAM was fast enough.
> This is what CP/M does. On cold start the entire system is loaded.
>Once loaded, the vector at 0000h is altered to point to the CP/M BIOS
>warm start routine and hence transferring program control to that
>address results in a warm start. (loading of BDOS and CCP, but
>generally not BIOS. Some reset the IO byte, some do not.)
>
> -Frank
--
Jeffrey Jonas
jeffj@panix(dot)com
The original Dr. JCL and Mr .hide
No; on an Amstrad box running CP/M, the ROM is paged out and JP 0 works
just like on all the other CP/Ms.
Jeff Jonas wrote:
>
> I guess I've never lost the Zilog mindset: starting ROM at 0 seems quite natural
> since the "PC" locating things at the "top" of memory created holes in the RAM,
> thus artificial low ram/extended/expanded/hi-ram, the "640 k limit", etc.
Umm, well, not really. The 640k limit was an arbitrary IBM design
decision, and had nothing to do with the 8088. Extended and expanded
memory were/are ways of extending the address space beyond one megabyte,
and high memory was a bug in the 80286 that turned into a feature.
Locating ROM high in the address space actually is quite useful since
CP/M (which was the model business micro operating system of the time)
was located there. On a CP/M box, the 8080 and Z80 reset address is
actually a bit of a pain to deal with since you have to add hardware to
phantom or bank select a ROM there, or mimic a ROM by jamming the three
bytes of a call instruction onto the bus. In fact, because of the
organization of the low memory address in CP/M, NMI becomes difficult to
use and most machines that did use it added hardware to redirect it.
Some chips are easier to work with in this regard than others. The
6502 bunched the start vector up in the top of memory with the break
vector and the interrupt vector. Generally, in a 6502 system you can
fix a ROM in the top of memory, and burn the break and interrupt vectors
in the ROM to point to low memory where you then put the vectors, this
allows user software to alter them as needed. The 68000 puts the reset
vector in the interrupt vector table. You can implement a similar
scheme to redirect to another location in memory, or you can bank switch
a ROM like a CP/M machine. The choice depends on whether you want to
add a flip-flop to your hardware, or devote 4k of your bootstrap ROM to
redirecting the vector table.
> Ah, all the wonderful exploration of memory management with
> small address spaces. I was sooooo tempted to make my own Z80 MMU
> using the M1 line for DEC-style separate instruction and data address spaces.
That created problems with immediate data, since if I remember
correctly M1 isn't asserted when fetching immediate data. Someone in
the know care to enlighten the rest of us?
> I remember one machine with hardware that copied the ROM to RAM upon power-on
> since the ROM was too slow to run direct, RAM was fast enough.
That was quite common, but not usually because of slow ROM. Say a
machine divided memory in half, right at 32k. ROM occupies the lower 4k
when switched in, and boot code is designed to start at address 0. The
ROM loader would copy itself to memory starting at 32k, then jump to the
ram copy, then switch in RAM, then load the first sector of the disk
starting at address 0 and transfer control to it. Microsoft's macro
assembler provided the .phase psuedo op to allow you to write this kind
of code.
-Frank
Ah Okay, thanks John! :-)
Well you'll probably know by now I haven't done any low-level stuff under
CP/M on the Amstrad & the only think I've touched under CP/M Plus on the
Amstrad is Generic BASIC! Come to think about it the only sort of assembly
I've done on the Amstrad is what the Firmware provides & I'm assuming
Firmware doesn't exist under CP/M Plus (only BDOS!).
Ross.
. .
|
\_/