Recommend a dev environment
It's been a while since I last wrote any Z80 assembler - must be over 20 years, and since I wrote any spectrum Z80 assembler more like 25 years. I need to write a small program which I intend to run on a genuine machine - not an emulator however I figure it will be much easier to develop on an emulator initially.
So here's the question, whats the best way of developing assembler with all current emulators and modern computer facilities combined with the old spectrum based assemblers etc?
Are there any emulators that will let me step through the code at execution? Are there any assemblers that will let me write the code in my own code editor on the mac or pc and then build and run into an emulator, or failing that any way of transferring the code from my pc or mac code editor into a file that can be loaded into an emulator.
Seems like a lot of questions, but I guess what I'm asking is... What is generally considered to be the best way of approaching machine code development these days? (don't want to go back to my early days of hand generating it by writing it all down, working out the hex code for the machine! :-P).
BTW: I tend to run FUSE on Mac OS X mostly and I do know that this has a debugger feature which could prove very useful but haven't really experimented with it yet.
So here's the question, whats the best way of developing assembler with all current emulators and modern computer facilities combined with the old spectrum based assemblers etc?
Are there any emulators that will let me step through the code at execution? Are there any assemblers that will let me write the code in my own code editor on the mac or pc and then build and run into an emulator, or failing that any way of transferring the code from my pc or mac code editor into a file that can be loaded into an emulator.
Seems like a lot of questions, but I guess what I'm asking is... What is generally considered to be the best way of approaching machine code development these days? (don't want to go back to my early days of hand generating it by writing it all down, working out the hex code for the machine! :-P).
BTW: I tend to run FUSE on Mac OS X mostly and I do know that this has a debugger feature which could prove very useful but haven't really experimented with it yet.
Post edited by Mr Ree on
Comments
My usual setup is SjAsmPlus (assembler) with UnrealSpeccy (emulator). This isn't very suitable when you want to develop for the original ZX models, because US does not emulate slow RAM, in this case I also use SPIN or other emulators.
That is what I've used for my projects, for one thing it means it's very easy to inline asm chunks into C programs that I'm compiling with z88dk.
the issue with sjasmplus is it's lack of compatibility with anything including itself :)
Winston used to use it for the spectranet rom code and it was a toatal PITA, the syntax not being the same across different versions. Took me ages to find a version for windows that had the same syntax as the one winston had used, and without bugs.
The other thing to be aware of is that all the assemblers have different ways of doing things like labels (and pasmo for example has various extensions that are totally unique to pasmo) this means that once you've written a load of code that one assembler will build you may have a hard time switching to another :(
I use Crimson Editor as a front end to with a small custom written program to handle some key presses. CE lets you have multiple tabs open so it's easy to spread your code across several files rather than lump it all together in one big one. Pressing F1 immediately saves all the open files, invokes the assembler and runs the emulator with the newly created target file (as well as saving backups of all edited files automatically). CE sits in one window and Spin in another so you don't have to reload either of them. Plus CE has a real easy way of handling the feedback from SjASMPlus - all the error & status messages are piped back into it after every assembly.
I've used few Z80 cross-assemblers (asm80, WLA, z80asm, as-z80, SjAsm without Plus). SjAsmPlus is my favorite so far.
ConTEXT works well for assembling and you can stick pasmo and SpecEmu on the Tools menu for maximum convenience.
The best option would probably be to try a few yourself and make up your own mind. The FUSE debugger is pretty powerful and, if you're familiar with gdb syntax than it would be easy to get to grips with. I've also used various other assemblers and they all have their good and bad points. sjAsmPlus has macros, which is useful, pasmo is very accepting of multiple different syntaxes, which is nice for working with other people's code, z80asm from z88dk has a support for libraries via the LIB/XLIB/XDEF/XREF directives which is great for larger projects.
It's fun playing around with all the various assemblers/emulators/debuggers and finding a set that works well for you...
- IONIAN-GAMES.com -
notepad++ :)
it's the dog's
Buy a second monitor and use it vertically, with a second context on it. Context is hard to be without.
If you stick to the dead standard stuff it can be compatible. However, it allows label syntax slightly different from everything else (so I had to write a script to convert everything). I still use it for short programs, tests, etc. where I'm not going to be investing the time to write a makefile and set up the linker etc.
If your project is going to end up needing more than one source file, then you are best off with an assembler that can make object files, and a linker to stick everything together at the end. It makes it much easier to maintain a larger more complex project. Being able to write libraries is handy. The latest GNU binutils is very good for this (get the latest, there are some bugs in the earlier releases for Z80). The problem with an assembler which doesn't make object files (in other words, the traditional 3 pass assembler - essentially, you have to include the source somehow to make one huge source file for the assembler to process) is you can easily end up with circular dependencies that are messy to resolve, and you often have to have files assembled in a specific order so that symbols can be referenced, and so that data/code that must be in a specific memory location actually gets assembled there. Linkers on the other hand take all this pain away, since you can make code or data sections for things that have to be in a fixed position, and symbol resolution is done at link time, not assemble time.
I was referring to it's command line syntax which varies wildly between versions :)
For anyone wanting to dip their toes into PC-based Spectrum machine code then there's no need for complications, just get an emulator you like, a text editor you feel happy with and an assembler that will tell your text editor where the errors are.
That's not quite true. If you are a one man coding machine (and this probably applies to 95% to be fair) then yes that is enough but if you ever plan to use code someone else wrote or make code you wrote available for anyone else to use then it has to be done with an assembler that supports libraries and linking. Macros are not an adequate substitution. Examples in the spectrum community are spectranet, sp1 and z88dk. Even if you don't plan to use or share code, it makes things much easier to manage your own private library of subroutines.
To be honest, I have always wondered why z80 assembler authors have thrown everything but the kitchen sink into their efforts but always seemed to stop short of adding linking ability, which is the one essential feature of a professional development environment.
Write games in C using Z88DK and SP1
I've done shared coding with no problems, we just told each other what bits of memory we could use and what we couldn't touch and left it at that. Never used a linker or library in any of them. The same goes for having my code ported over to other machines, it might have been a problem if the other people didn't know what they were doing but they were competent coders and just got on with it. Again no linking or libraries.
I will agree with you that community projects involving multiple coders benefit from structured programming protocols, but when programming a game on a simple 48K Spectrum (or even a +3 multiload) then it's really not needed.
Perhaps z80 assembler authors have not included linking because they looked at what they were building and thought it wasn't necessary. If it was really that important don't you think they'd have included it in the first place?
Currently playing around with my homebrew assembler to a) make it multi-pass, as I didn't realise so many assemblers did >2 passes as it's not something I've ever relied on, and b) bolt on some sort of library linking shenanigans. Some might say this is a pointless excercise as there are perfectly good assemblers in existence that already do all that... but that's not how I roll. :D
binutils-z80 + make + gedit + fuse
You will have to make your own linker script. As for debugging - fuse is useful but what we really need is an emulator that would expose debugging interface to the world instead of trying to provide a debugger. Something that could read and write memory and registers should do. The rest i.e. Interpreting symbols, etc should be done by an external debugger, not the emulator.
This is still a one-man development model where all subroutines are known to each programmer and the entire project is in his/her head. You do still have to hand link the two halves of the project by exchanging symbol files but this is not hard as long as you edit out the local symbol names by hand.
I know it's important because compilers would be impossible without it and sharing codebases across many authors over many years would be very difficult without it, no matter what the source language is :-)
z80 tools that you pay for, eg from zilog, IAR, rabbit, or used-to-pay-for hitech all include linkers. Of the couple dozen free choices, on the other hand, I think there are four with linkers. A few go part of the way by supplying a macro system that can hide local variables so that it is at least possible to conveniently share independently written code.
Most people in the current z80 community do not share code and have no intention to share code and there is nothing wrong with that but that is what makes it doable to go without a linker. For others these are the problems that a linker solves:
1. Distinction between local and global names to automatically resolve name clashes. Remember that subroutine you wrote 6 months ago that used the name 'loop' for a local label? Well if you plan on using it in the current project you'll have to inspect the code and make sure none of the names conflict with anything. Hopefully you can keep all the names in the ten k lines of code in your current project fresh in mind while you do this inspection. Maybe there is a system for naming -- hopefully you used the same system six months ago. Forget about naming systems if you're using code written by someone else altogether.
2. Use what you need and no more. You wrote this cool graphics library last year that has stuff for drawing lines, arcs, circles, stenciled outlines, filling, etc. In your current project all you need is to draw a line. Including the whole set of graphics routines would add 10k to your program size and you don't have that much available. Solution? Go through the graphics routines by hand, extract the DRAW part and then grab all its dependencies like calculate pixel address, modify screen address by moving left/right/up/down, etc. Hopefully you pull them all out so your project will compile. Want to make it twice as bad? Use someone else's graphics library because nothing makes it more difficult than to have to sift through someone else's file organization and dependencies.
3. Resolve dependency hell. I want to use this strtol function that can read a number in any number base out of a string being parsed from a file. Let's see, to use strtol I will need to grab l_neg_dehl, stdlib_consume_ws, strtoul_common and _errno. stdlib_consume_ws? Didn't I add that to the project already? Will have to check... Let.s see.. stdlib_consume_ws needs asm_isspace. strtoul_common needs stdio_ascii2digit, asm_toupper and l_mulu_40_32x8. If I used the small integer math lib, l_mulu_40_32x8 is standalone. If I use the fast integer math lib, I will need l_mulu_32_24x8, l_mulu_24_16x8 and l_mulu_16_8x8. Hmm there's a medium integer math lib too. Wonder what that needs and what if I change my mind later on? oops.. nearly missed it, strtol needs an include file of constants in "std_defs.inc", will have to add that one. That file's pretty big -- hopefully adding all those names to the global scope doesn't cause any name conflicts.
4. Separation of code and data. Want to make ROMable code or even to reduce the final binary size? Well then you need to separate the variables area from the code area. By hand this takes some discipline. For example, to reuse a random number generator you need to place the seed variable in RAM someplace. Doing this by hand usually means keeping a separate file of defines. It also means you need to inspect the code you reuse for variables and transfer their locations / definitions to this separate file.
5. Multiple code and data segments. Bankswitched programs have code and data that occupy the same address range. Linkers that support multiple segments can automatically handle this sort of situation.
If you think these are the sorts of things a computer should be doing you're right. Codebases and projects with some complexity do exist on the Spectrum and without linkers available, they would be unnecessarily difficult to pursue. It is also true not having this sort of facility available places a limit on how complicated a project can become, unless all code is written using the one-person model (and relying on code written by one person also places a limit on complexity since any one person only has so much time and commitment).
Write games in C using Z88DK and SP1
A full-blown linker model is overkill for something like this. The only times I've found myself needing one are on OS/firmware code, and enormous 128K demos that hop between memory pages like crazy.
My vote is for Pasmo (with a Makefile and various odds and ends like zmakebas and bintap to manage the build process if it outgrows a single command line), and occasional use of the Fuse OSX debugger (although most of my debugging consists of staring at the listing and thinking. I don't think there's anything available that will truly let you debug Spectrum Z80 at the source-code level).
I've not seen the OSX fuse debugger, but the windows and linux version is fairly limited compared to spin's.
I know spin's debugger had lots of bugs etc but still I think it's the best debugger I've ever used. You can edit the code in memory as you step through it etc, it's very versatile
http://zxspectrumdev.blogspot.com/2009/01/setting-up-development-environment-on.html
Precisely. Most of the support for a Linker seems to be predicated on being able to use someone else's code easily - or recycling code that you wrote but can't remember what does what. Simplification I know, but if that's the method some people are comfortable with when they code then that's fine. But you don't need a Linker model to write a game for the 48K Spectrum - or any Spectrum really - especially so if you are a one man band coder.
In fact you don't even need a cross-assembler, you can use the Spectrum and something like the OCP Assembler and develop "just like the old days" with not a Linker or makefile in sight. That approach works just fine, even managed to get a program out of it that sold a copy or two myself. Nerve wracking as hell because you have no support or debugging facilities whatsoever. But a lot of fun. :)
It's a good step-by-step for setting up an IDE on the Spectrum. I looked at PASMO but couldn't see a way of getting an errors\warnings list out of the program. If I (say) have a missing label or syntax error in the source code does anyone know if it gives error-line feedback or do you have to guess where the error(s) are yourself?
No problem getting error-line feedback here:
$ cat pasmotest.asm org 0x8000 ld a,1 this is not an opcode ld a,2 ret $ pasmo pasmotest.asm pasmotest.bin ERROR on line 4 of file pasmotest.asm ERROR: Macro name expected but 'is'foundReplacing ld cb,6143 with ld bc,6143 and reassembling now produces no errors whatsoever......despite the invalid ORG, misuse of A register and mistyped ldir.
Do you get any error messages for these three lines on your PASMO setup?