News:

Printed Amstrad Addict magazine announced, check it out here!

Main Menu
avatar_Bruce Abbott

CHAMP Assembler/Debugger ported to Amstrad CPC

Started by Bruce Abbott, 11:59, 16 January 14

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Bruce Abbott

Here is my port of CHAMP (http://www.worldofspectrum.org/infoseekid.cgi?id=0008012) to the Amstrad. This was the main development tool that I used on my CPC664 back in the 1980's.

CHAMP was an assembler/debugger/monitor program supplied on a 'free' tape for use with the Commodore 64, Sinclair Spectrum, and BBC micro. I figured that it should be possible to 'port' the Spectrum version over to the CPC, since they had the same CPU and fairly similar architecture.  It only took me a few days to get it up and running, but more than a year of tweaking to make it really useful. 26 years later, with the aid of WinAPE and a modern PC I finally had a chance to finish the job - and perhaps make it even better!         

I have made a number of enhancements to the original Spectrum program, including:-
- ROM resident for smaller memory footprint, faster loading and protection from corruption. 
- Source code checked for corruption after quitting and re-entering the assembler.
- Accesses up to 512K RAM. Assembler can create object code in expanded memory. Debugger can read from one bank and write to another, load/save files to/from expansion RAM etc.
- Debugger can read upper ROMs.   
- Execute RSX commands from within the debugger.
- Faster scrolling of text in assembler, some other speedups.
- Automatic conversion of keywords from lower case to upper case.
- Uses left-hand side of Mode 2 screen. Right-hand side is available for displaying system messages or user program output.
- Right-hand window is also used to display Help text on startup.     

This is a work in progress and I still have a few ideas to try out, but I am releasing this version now in the hope that someone might find it useful (or least entertaining). The attached zip file should contain the source code (for WinAPE), binary ROM image, documentation, and a disc with some example code (including source code and executable for my original Amstrad port).   

Any criticisms/bug reports/suggestions are welcome, but please read the documentation beforehand!
   

TFM

Hi Bruce!

This seems to be a really great set of tools!!!  :)  In some regards it seems to be even superior to MAXAM, f.e. access of expanded RAM.

The biggest Plus of your Tool-kit is that it really runs on a CPC, instead of being some other cross-dev. progs one needs a PC for.

Another positive point, it seems to be syntax compatible with MAXAM (my up to date favorite, since it runs reliable and stable even with 500 KB of source at once).

I will give your great assembler a go soon, and I'm very excited about it.


One suggestion: It would be great if your assembler can assemble itself without the necessity of using an assembler on the PC side. Just an idea.  :)


Suggestion two: Would be nice if you could include the second register set of the Z80.

TFM of FutureSoft
Also visit the CPC and Plus users favorite OS: FutureOS - The Revolution on CPC6128 and 6128Plus

Bruce Abbott

Quote from: TFM on 18:50, 16 January 14
One suggestion: It would be great if your assembler can assemble itself without the necessity of using an assembler on the PC side. Just an idea.
It could assemble itself, but with over 700 labels that can only have 6 characters I was running out of descriptive names! I may look into a way of compressing the label names down to 6 characters and translating the source into CHAMP's tokenized format, for anybody who wants to go fully 'retro'.

BTW the disc contains source code for an old version of CHAMP which can be assembled by itself, however this is missing some static data which has to be loaded into memory separately and merged with the object code (I used to just load the entire CHAMP executable into the 2nd memory bank, then assemble over the top of it). This made the source code about 230 lines shorter, but for WinAPE I wanted to have all the static data in the source code in case I wanted to modify it.         

QuoteSuggestion two: Would be nice if you could include the second register set of the Z80.
I didn't worry about the alternate register set because the OS makes heavy use of those registers during interrupts, so I thought it was best to leave them alone. However there's no harm in just reading them, so  I have now added the alt register set to the debugger's register display. The system values will be displayed when you trace any code.



TFM

Ah great that nice. A lot of my routines use the second register set that make things way more quick.Of course then the interrupts must be off and regs. must be restored.




The limitation of the label to six letters is indeed a bit small. Is it due to the way the editor works?
Could it be expanded in some way?




Thanks a lot for the update!!!  :)  Great work!!!  :)
TFM of FutureSoft
Also visit the CPC and Plus users favorite OS: FutureOS - The Revolution on CPC6128 and 6128Plus

Bruce Abbott

Quote from: TFM on 22:40, 17 January 14
The limitation of the label to six letters is indeed a bit small. Is it due to the way the editor works?
Could it be expanded in some way?
CHAMP stores labels in an array which has 8 bytes per entry (6 bytes for the label and 2 bytes for the value). The size of the label field could easily be increased, but there are some caveats:-

1. The source code will use more memory and disc space. Since the amount of space allocated per label is fixed, short labels will have more 'wasted' space.   

2. You lose compatibility with files created by the standard 6 character version. However old files could be translated into the new format.   

3. Longer labels increase the length of assembly lines on screen. According my calculations, allowing labels over 8 characters long may cause some lines to exceed 40 characters, and then you won't be able to type them in! This limit can be overcome by increasing the screen width, but will slow down scrolling speed and there won't be enough room for the help text. There is also a hard limit of ~62 characters per line due to the line length being stored in 6 bits.

I think the maximum label length can be increased to 8 characters quite easily, so I will try this first. Increasing the on-screen line length will require major work, but I will have a go at this too. To address scrolling performance I will attempt to implement hardware screen roll in the editor. Hopefully it won't require much more code, as space in the ROM is getting tight!

TFM

Oh, I see, that's not as easy as I did hope. I guess six characters for labels are fine too. Since one label uses 8 bytes it fit's nicely a 256 page (32 labels). If you use eight characters, then the label need 10 bytes and one of them would reach over the page end, which may cause problems (if the assembler uses INC L instead of INC HL).


One more of my wild ideas... Would it make sense to split up the whole program into two ROMs? Today there is enough of ROM space and it would allow you to make things more quick f.e. add hardware scroll etc. as you mentioned before.


Happy Saturday!  :)
TFM of FutureSoft
Also visit the CPC and Plus users favorite OS: FutureOS - The Revolution on CPC6128 and 6128Plus

Bruce Abbott

Quote from: TFM on 19:10, 18 January 14
Oh, I see, that's not as easy as I did hope. I guess six characters for labels are fine too. Since one label uses 8 bytes it fit's nicely a 256 page (32 labels). If you use eight characters, then the label need 10 bytes and one of them would reach over the page end, which may cause problems (if the assembler uses INC L instead of INC HL).
Actually that part was quite easy. The IndexSym function was multiplying by 8 using three 'ADD HL,HL' instructions. I just copied HL to DE and then added it back after the second 'ADD HL.HL' to multiply by 5, then the last 'ADD HL,HL' made it multiply by 10.     

It took me a while to find all the places in the code where label and symbol sizes were hard coded, and to change the TAB values. The (hopefully) last issue - which I just fixed a few minutes ago - was that labels that hit the end of the line were giving an error. This was caused by the end of text check not accepting NULL as a valid terminator!
     
CHAMP seems to be working fine with 8 character labels now, but before releasing it I will do some more tests to make sure I haven't missed anything...



Hicks

This is very interesting. I will take a look to the notice and make some tests and then give you my feedback...
Do you consider it as a "work in progress" (= it's possible to change some things according to the needs of the users) or a "quasi-final version" (= no major changes are planed)?

Hicks

#8
A first question: if I load the "hello.asm" source code (L => hello.asm) and assemble it in RAM (A => 2). Then I switch in debug mode (D) and execute it (.#8000). It works, but when I try to go back to the assembler (A) Champ say to me that my source code is corrupted and clean it. Is it normal?

A suggestion: a shortcut will be nice, for exemple : from the assembler, I press "CRTL+A" and he do "A => 2 + D + .#8000.
A "ENT $" (cf. DAMS) instruction will be nice to give the entry adress of the source code (and then we can just type "." without adress).

It seems also that the "math" is a weak point if only simple additions and substractions are tolerated... We often need multiplications, divisions and "complex" operations with labels (i.e. adr/256+#80) to make the code more flexible/dynamic.

Sorry for this "critical message" which is not representative of all you nice work!

Bruce Abbott

Quote from: Hicks on 13:31, 21 January 14Do you consider it as a "work in progress" (= it's possible to change some things according to the needs of the users) or a "quasi-final version" (= no major changes are planed)?
Right now I am leaning towards "quasi-final version", but I am open to suggestions.

As well as 8 character labels, the next revision will have a less quirky line editor. DEL now acts like a true backspace and CLR like delete, with insert editing of comments and operands (having to retype most of a line just to insert one character was a pain!). Also I have made the tabbing function more consistent.  Hopefully it will be ready for uploading tomorrow...
 

Bruce Abbott

Quote from: Hicks on 14:47, 21 January 14
A first question: if I load the "hello.asm" source code (L => hello.asm) and assemble it in RAM (A => 2). Then I switch in debug mode (D) and execute it (.#8000). It works, but when I try to go back to the assembler (A) Champ say to me that my source code is corrupted and clean it. Is it normal?
No, it's not normal. Seems a bug crept in that I didn't notice! Please try the attached update (V2.10d).

QuoteA suggestion: a shortcut will be nice, for exemple : from the assembler, I press "CRTL+A" and he do "A => 2 + D + .#8000.
A "ENT $" (cf. DAMS) instruction will be nice to give the entry adress of the source code (and then we can just type "." without adress).
Providing a shortcut key is easy, but adding commands to the source code is tricky. Perhaps the ORG directive could also set the entry address?

QuoteIt seems also that the "math" is a weak point if only simple additions and substractions are tolerated... We often need multiplications, divisions and "complex" operations with labels (i.e. adr/256+#80) to make the code more flexible/dynamic.
Yes, CHAMP's math is quite weak. I am considering adding multiplication and division.  Meanwhile you will just have to calculate those complex operations by hand...

TFM

Quote from: Bruce Abbott on 16:18, 21 January 14
... Perhaps the ORG directive could also set the entry address?


That's a good thing. So compatibility to MAXAM is there.  :)
TFM of FutureSoft
Also visit the CPC and Plus users favorite OS: FutureOS - The Revolution on CPC6128 and 6128Plus

Hicks

Thanks for this new version.
The "corrupted source" bug disappear, nice!

If the ORG directive set the entry address it can be a problem because we often put at the begining of a source code a list of DEFB/DEFW/DEFS and put the "ENT $" after them, when the instructions to execute starts. So if the first byte of code is the entry address we can't code like this. An alternative idea: is it possible to give 2 parameters to ORG? The first will be the starting address of the source and the second the set entry address? And then, we can put a label at the begining of the code? Like this:


        ORG #8000,start
;
byte    DEFB 0
word    DEFW 0
;
start
        PUSH AF
        PUSH BC
        ...


Easier to implement?

Bruce Abbott

Quote from: Hicks on 17:21, 21 January 14is it possible to give 2 parameters to ORG? The first will be the starting address of the source and the second the set entry address?
Yes, that could be done relatively easily.  Another possibility might be to have a reserved label which sets the entry address, eg. _start.

I will also look at expanding the directive set, as other functions such as WRITE to file, INCBIN and STR may be worth implementing.     

Hicks

Yes, the reserved label idea is a good idea too.

Two other questions:
- in the notice, you wrote that #8000-#9FFF area must be free. What do you do in this zone? (maybe a label address table or something like that?) It's strange because I can assemble a source in #8000... Is it possible to move it in the expanded RAM, I mean, if I have a 512kb CPC can I put this area out of the base 128kb in order to have the full memory free to use?
- same question for the source code: can I store it out of the base 128kb? I think it's related to the "X" command but I didn't test it yet...

If the 2 answers are "yes", then it's a kind of killer-argument to DAMS!

Optimus

That looks good, even if I have 10 years to code in the real CPC, I am gonna check it. I used to work on Maxam, so it's good if it's Maxam-like.

Bruce Abbott

Quote from: Hicks on 12:01, 22 January 14you wrote that #8000-#9FFF area must be free.
#8000~#9000 is free. CHAMP doesn't use it.

QuoteIs it possible to move it in the expanded RAM, I mean, if I have a 512kb CPC can I put this area out of the base 128kb in order to have the full memory free to use?
Yes. Using the X command, you can tell the assembler to send its output to any 64k bank. I used this feature when using CHAMP to assemble itself (since it doesn't like being overwritten with new code while it's running!) and for assembling ROMs.   

I expanded my 664 to 256k of RAM by removing the 64k DRAM chips and replacing them with 256k chips. To access the extra RAM I developed a daughter board which emulated the 6128's memory mapping and provided addressing of the upper 128k. The CRTC was also able to access the extra memory, allowing instant switching between between 16 different screens! (think of the animation possibilities...). I also put a switch on the side of the case which swapped the upper and lower banks and triggered a non-maskable interrupt, so I could switch between two 128k memory maps and have a 'multiuser' machine. I could write and assemble code in one bank, switch over and run it on a 'clean' machine in the other bank, then switch back to the first bank and continue writing code...   

Sadly my 664 is no more and I lost the circuit diagrams. I could do similar mods to my 6128, but I would now rather keep it in it's original (mint) condition, and work within the limitations of the stock machine.     
     
Quote- same question for the source code: can I store it out of the base 128kb?
Not at present. It should be relatively easy to have the source code stored in a single expanded memory page (16k max), but using more than 1 page would be bit trickier and might slow it down a bit. It takes a long time to type in more then 16k of CHAMP source code...

I am thinking of getting CHAMP to use expanded memory for all of its RAM requirements (32k should be enough), keeping base RAM free for the system and user programs. The only question is which pages can I allocate, without clashing with other utilities?
         

TFM

Well... for CC the source exceeds 500 KB by far, and I'm not commenting much.  ;)  Dunno if 32 KB is enough, maybe it could be more dynamic?


Most of the other utilities use E-RAM from C4-C7, but this is very few, so you could disregard it.  :)
TFM of FutureSoft
Also visit the CPC and Plus users favorite OS: FutureOS - The Revolution on CPC6128 and 6128Plus

Bruce Abbott

#18
Quote from: TFM on 18:39, 22 January 14
Well... for CC the source exceeds 500 KB by far
What is CC?

The last version of CHAMP that I produced on the CPC had 4720 lines of source code. In CHAMP's tokenized format this took up 23k, but expands to 83k of plain text. It has a little over 700 labels, which is getting close to CHAMP's limit of 1023.

V3 is now up to 194k of plain text, mostly due to the addition of static data and liberal commenting. This equates to ~ 64k of tokenized source. I may try stripping out the comments to see if CHAMP can still assemble itself. However for a project of this size it makes sense to cross-assemble using a PC (only a masochist uses an inferior tool when they have access to a better one). 

BTW in 1987 I used CHAMP on my 664 as a cross-assembler for a commercial project (an electronic gambling machine). The CPC was connected to the target via an EPROM emulator that I built. I also used it to develop an arcade game for the Sega SC3000 (I still have the source code for this project!).
     

QuoteDunno if 32 KB is enough, maybe it could be more dynamic?
It could be done, but on an 8 bit machine there comes a point where the overhead is not worth it. The obvious way to access expanded memory transparently is with the same code I use now in the debugger, which replaces every RAM access with a CALL that switches the correct page in and out automatically. However this will slow down the assembler and significantly increase code size (might need to split CHAMP between two ROMs).   

Alternatively I can just directly access the expanded RAM page at &4000~&7FFF. This has insignificant overhead, but limits the source code size to 16k. Perhaps I could detect crossing the page boundary and switch further pages in as necessary without adding too much overhead.  It might even be possible to switch in the whole 64k at once (bank 1 only?) but the OS would have to be disabled while using the assembler.     

QuoteMost of the other utilities use E-RAM from C4-C7, but this is very few, so you could disregard it.  :)
OK. I guess the first and second pages of bank 1 would be the safest to use as they are present on the 6128, and it still leaves 2 pages free in bank 1 (&8000~&FFFF).

TFM

Oh well, I still use Maxam on CPC side instead of Cross-Assembling. But I can use it on an emulator, so it's very quick in Turbo mode. I wouldn't call it inferior. In contrast regarding system stability f.e. it is superior to to the PC, especially when running Windows. Sure on PC side you got all kind of gimmicks, but I don't need them. I also could use Maxam II under CP/M to enjoy Macros, but I like to have the assembler in ROM - and this is what I like very much about your assembler too.  :)


CC is my last game Cyber Chicken (see: Cyber-Chicken for CPC). I just took a look at my source code disc. It contains now about 650 KB of source (plain text), that would be about 220 KB in compressed format. Now CC is just a regular sized game, I got bigger projects too.  ;D
TFM of FutureSoft
Also visit the CPC and Plus users favorite OS: FutureOS - The Revolution on CPC6128 and 6128Plus

Bruce Abbott

Here is V3.00b, which has the following changes:-

1. Labels can be up to 8 characters long. Note that .asm files created with older (6 char) versions of CHAMP are not compatible!

2. Insert editing in Comment and Operand fields (overwrite editing still used in Label and Opcode fields).   

3. New directives:-

ENT label/address ; set code entry point (PC register) in debugger.

INCB "filename" ; insert binary file into object code.

4. Hitting <ESC> in <insert> mode returns to <assemble> mode. Escaping from a blank line no longer gives an error.

Next on my list of things to add are the directives WRI (write object code to file) and STR (define string with bit 7 set in last char), and math operators * (multiply) and / (divide).


     

Duncan

Marvellous.
In ASM mode. Pushing "D" jump quickly in Debug mode. (which is nice.)
In Debug mode. I have to push "A"+"enter" to jump in ASM mode. (which is less nice.) :)


Great job anyway.

Hicks

Very nice news!
I still have to do more tests to make new suggestions (especially related to the "X" command), but the new version bring nice features.

In the notice, I read:
QuoteNOTE: Assembling to RAM is potentially dangerous. To avoid
overwriting memory used by CHAMP or the OS etc., make sure
that an appropriate ORG directive has been entered. The Info
command will tell you what memory areas CHAMP is using. The
area from &8000 to &9FFF should be free.


But you say that #8000 to #9000 is free... So I think it's a little mistake in the notice and imagine that #9000 to #9FFF is reserved to CHAMP ?

A nice improvement of your "INCB" directive will be to allow 1 or 2 parameters like :
- address entry of the file
- bank number (by bank I mean #C4, #C7, i.e. bloc of 16kb. I think you called it "page" in another post... For me a "page" is a bloc of 4 banks, i.e. 64kb.)
So, for example :
INCB "file.bin",#6000,#C4
And the top of the top would be to detect if the file has already been loaded in order to load all the files only the first time we assemble our code!

"WRI" directive is a good idea too.

Quote
(only a masochist uses an inferior tool when they have access to a better one). 

Does it mean that you think that it's masochist to use Champ today instead of cross-assembler? :)

TFM

INCB is really a great idea!!! Do LOAD and WRITE work like in Maxam?


@Hicks: Amstrad totally confused my with blocks and pages, one is 64 KB and one is 16 KB. I gave up and just use that handy 16 KB blocks.... err pages... or what ever.  :laugh:
TFM of FutureSoft
Also visit the CPC and Plus users favorite OS: FutureOS - The Revolution on CPC6128 and 6128Plus

Bruce Abbott

Quote from: Hicks on 16:57, 28 January 14
In the notice, I read:
But you say that #8000 to #9000 is free... So I think it's a little mistake in the notice and imagine that #9000 to #9FFF is reserved to CHAMP ?
What I meant was that normally, &8000~&9000 will be free. I need to update the manual...

QuoteA nice improvement of your "INCB" directive will be to allow 1 or 2 parameters like :
- address entry of the file
If by 'address entry' you mean the address the file will be loaded into, you can set that with ORG. ie:-

ORG #6000
INCB "file.bin"


Quote- bank number (by bank I mean #C4, #C7, i.e. bloc of 16kb.
The idea of INCB is to embed binary data (eg. graphics, tables) into the object code, which is a contiguous area of memory that can be saved as an executable file. If you want to load data into different memory blocks then you should write some code to do it at run-time. If you want to create a large executable file that won't fit into normal memory, use the debug command X1 to create the object code in the second 64k.

QuoteI think you called it "page" in another post... For me a "page" is a bloc of 4 banks, i.e. 64kb.
It's confusing...

According the 6128 manual, a 'bank' is 64k and a 'block' is 16k. I recently discovered that some Amstrad programmers use 'block' for 64k and 'bank' for 16k. This is backwards, and does not agree with the definitions used on other operating systems.

I used 'page' to refer to the 16k blocks which are switched in at &4000~&7FFF. In standard memory management parlance, 'pages' are blocks that are mapped into physical address space one at a time (like the pages of a book). If this causes confusion then I will refer to them as 'blocks'.       

QuoteAnd the top of the top would be to detect if the file has already been loaded in order to load all the files only the first time we assemble our code!
This is getting into the realm of 'make' files, a bit too sophisticated I think. I prefer that everything be recreated each time the assembler is invoked, so there can be no confusion about whether the object code is up to date. Also, it is possible to INCB a file and then ORG into the middle of it to overlay more code/data, requiring the file to be reloaded if the other code changes.       

Quote"WRI" directive is a good idea too.
Yes, I need to implement this ASAP (using the debugger to write the file is a pain!).

QuoteDoes it mean that you think that it's masochist to use Champ today instead of cross-assembler? :)
If you are using a physical Amstrad machine (or trying to reproduce the same experience with an emulator) then it isn't masochist, it's Retro! However I find my productivity increases dramatically when using a good GUI-based IDE.
 

Powered by SMFPacks Menu Editor Mod