Z80 TRAP and CP/M
Don Y
dgy at DakotaCom.Net
Tue Apr 4 21:23:48 CDT 2006
Roy J. Tellason wrote:
> On Tuesday 04 April 2006 09:08 am, Don Y wrote:
>> Roy J. Tellason wrote:
>>> On Monday 03 April 2006 12:57 am, Don Y wrote:
>>>> I think the real reason (?) goes to a difference in cultures between
>>>> register rich and register poor machines IN THAT TIMEFRAME.
>>> I think you're probably right...
>>>
>>>> E.g., if you are writing code for a 68xx, you have little choice
>>>> but to do everything in memory addressing. Whereas if you are
>>>> using 8080/8085/Z80 et al., you just get used to *keeping* things
>>>> in registers (I can recall spending lots of time evaluating
>>>> which arguments I would put in which registers so I could
>>>> *keep* them there -- or somewhere else in the register set -- for
>>>> the duration of the algorithm... XCHG being a favorite tool
>>>> in those cases!)
>>> Yeah. Though XTHL was another one...
>> As was PCHL. But, XCHG was lots of bang for the buck (4 clocks?)
>
> Yes. And I often wished that they'd had one that would work with BC, as
> well... :-)
The typical usage was HL & DE for source/destination pointers
and BC as length/byte count. So, you could
LXI H,...
LXI D,...
...
DAD B ;HL points to something
XCHG ;save HL in DE, get at contents of DE
DAD B ;DE points to similar "thing"
...
>>>> Moving to something like a 99000 can be terribly distressing
>>>> for the register rich crowd to become accustomed to! ;)
>>> I found, though, when I was doing some z80 stuff a while back that most
>>> of the time I'd use one pair for an address pointer and maybe one other
>>> besides the accumulator and that was it, over 90% of the time.
>> Z80 is a different beast from the 808[05]. You write code differently for
>> it because it has a much richer instruction set.
>
> But I never used most of that stuff. Never got around to doing anything with
> the index registers, the alternate set, or a lot of those "specials" that
Alternate register set was ideal for interrupt service (assuming
IRQs aren't nested *or* you restrict the alt registers for use by
a single IRQ that can never interrupt itself). Consider the
cost of saving all of that state and restoring it before RETI
and you can see how quickly you can save a lot of time!
> were added. I kinda liked relative jumps, though, since it made it way
> easier to do relocatable code and plus they were a byte smaller. :-)
A favorite trick was to finish a product. Then grep for all
CALLs. Sort this list to come up with the N most common CALLs,
and then assign those to the "unused" RST's. You could often
save 500 bytes of code with that 10 minute exercise...
>> But, if you are doing things like adding an 8 digit BCD number to another 8
>> digit BCD number, you quickly discover that you need a lot of registers (two
>> pointers for the two arguments -- assuming the destination is one
>> of these as well, a "digit counter", the accumulator and, of course, the
>> carry).
>
> I suppose. I guess it all depends on what you want to do...
>
>>> Oh, and the little monitor program that I was playing with didn't push a
>>> parameter on to the stack, it put it inline, right after the call to
>>> some subroutine -- the called code would pick it up and use it and adjust
>>> the stack pointer to just past it for the return. :-)
>> Yes, a favorite trick for "printing" strings, etc.
>>
>> CALL OUTPUT
>> DB 'Hello, World!'
>> <insert next instruction here>
>
> Just so.
We would often develop our own interpreters to make some of this
stuff more efficient to code. This would get coded in-line
with appropriate macros. For example:
STATE IDLE
ON '0' THRU '9' GOTO IDLE EXECUTING Accumulate_Digit
ON BARCODE GOTO TEST EXECUTING Clear_and_Read_then_Test
ON CLEAR GOTO IDLE EXECUTING Clear_Accumlator
ON ENTER GOTO TEST EXECUTING Test_Value
ENDSTATE
STATE TEST
ON GOODVALUE GOTO ACCEPT EXECUTING Process_Value
ON BADVALUE GOTO REJECT EXECUTING Signal_Error
ENDSTATE
So, with ~25 bytes, I can code a numeric data entry routine
(trivial example) in a way that actually is reasonably easy
to read.
>>> I have to dig out that code, anyhow, there were a few little tricks in
>>> there that I think I want to use again. Like funneling everything
>>> through a dispatch table, so that un-programmed EPROM showing up as
>>> "FFFF" in some entries would be handled automatically ("CRASH!" :-),
>>> ferinstance.
>> Or, using INR M to 'test' flags.
>
> Yep!
THogh this caused all sorts of problems when I got my first
ICE! :-( (think about it :> )
> Sometimes I like the absolutely minimalist approach to things, too. One of
> these days I'm gonna dig that code out, burn it, and see how small a z80
> box I can build that'll still prove useful for all sorts of things. I sure
> have enough of those parts on hand here...
I have a tiny multitasking executive that runs in a handful of
bytes. Slick as snot -- if you adopt its coding style.
More information about the cctalk
mailing list