ah, yes. When I did tests, I had projects for MSX, Spectrum and Amstrad. Sp, definitively there was a mix. It could have been on a Spectrum/Amstrad project!
Hi guys, I released version 0.6 with all those changes that have been building up over the past five years. Quite a long list of improvements!
Download: Glass project page
Newspost: Glass Z80 assembler 0.6
oh wow, lots of very interesting changes! Thanks Grauw! I Wasn't aware of that >>> operator
Nice work!
I really love these two new features (I had to make a workaround for it in previous versions)
- Macro definition symbol offsets are now included in the symbol file.
- Symbols with integer equ values are now included in the symbol file.
Small remark however:
You should not include symbols that are itself being imported via an include command. This causes 'symbol redefined errors' when compiling other source files that use the same imported symbols.
example:
lib.asm (contains macro's and constants)
run.asm (output = run.com, loads and executes scene*.dat files)
scene0.asm (output = scene0.dat)
scene1.asm (output = scene1.dat)
scene2.asm (output = scene2.dat)
run.asm includes lib.asm
scene*.asm includes lib.asm & run.sym
When compiling scene*.asm you get a 'symbol redefined error' because symbols in lib.asm also are present in run.sym.
What really would be nice is a feature for defining a symbol namespace (like a prefix for the labels in the generated symbol files). It would then be possible to do a 'include "*.sym"' without any problems.
Hey inchl, glad to hear you like it.
I myself primarily use the symbol file to load symbols into the debugger. It’s interesting to hear how you’re using it. It sounds like there could be overlap with features like modules, exports and linking. I’m thinking of ways to expand Glass with functionalities in that direction, but I don’t have a clear picture yet. At least now that I have finalized this release I can start looking at making some larger changes again.
You should not include symbols that are itself being imported via an include command. This causes 'symbol redefined errors' when compiling other source files that use the same imported symbols.
About that, in principle include
is considered as a textual replacement, like the source is included in a single big file. From that perspective it would be strange to exclude symbols, especially if it’s only for macros and constants. It would also omit those symbols for use with a debugger, where they are useful.
What really would be nice is a feature for defining a symbol namespace (like a prefix for the labels in the generated symbol files). It would then be possible to do a 'include "*.sym"' without any problems.
About this, in the future I might add a more obvious (dedicated) way to introduce a block scope, but for now you can put the includes in a scope using:
label: PROC ; … stuff here … ENDP
Then all symbols inside will be prefixed by the label. With that you should be able to filter them out from the symbol file in your build script, or alternatively, if you use a different scope name in the runner and in your scenes, there should be no name clash.
Would’ve loved to talk some more about it at the fair Saturday, but unfortunately I can’t make it.
Hi Grauw,
first of all nice work, this keeps evolving.
Here is just a quick feedback and a bug report:
First of all, I would really like to see some relaxed keyword rules, some of my sources use variants, e.g. "defb/defs/defw/..." instead of "db/ds/dw/...", or "ex af,af" instead of "ex af,af'" (with the apostroph at the end). This is a bit of annoying extra work when cross-assembling code, and after every error and rerun, I wish glass wouldn't be so picky. But I understand the point that various alternative options pollute the code.
Now for the bug report:
I often use the following construct to force a certain code or data to be at a certain address:
ds "target-address" - $ - "org-address"
Here is a full example where I want the code to be at 0x10, then fill the memory until 0x30 with 0xff, and put the data at 0x30:
org 0x10 ld hl,1234 ld de,4567 ds 0x30-$-0x10,0xff db 0x40,0x41,0x42
Note that I intentionally used "0x10" (instead of e.g. "0x100") for this example to trigger the bug later with just a few lines of code.
This will put the code at address 0x10 and the data at address 0x30. And it works with Glass *until* the code exceeds 0x10 bytes (or whatever the org was set), so if you add some more lines, the assembler throws the following error message:
Exception in thread "main" java.lang.IllegalArgumentException: Negative initial size: -2
at java.io.ByteArrayOutputStream.(Unknown Source)
at nl.grauw.glass.instructions.Ds$Ds_N_N.getBytes(Ds.java:75)
at nl.grauw.glass.Line.getBytes(Line.java:119)
at nl.grauw.glass.Source.getBytes(Source.java:91)
at nl.grauw.glass.Source.assemble(Source.java:53)
at nl.grauw.glass.Assembler.writeObject(Assembler.java:72)
at nl.grauw.glass.Assembler.main(Assembler.java:59)
Here's a full example:
org 0x10 ld hl,1234 ld de,4567 ld hl,1234 ld de,4567 ld hl,1234 ld de,4567 ds 0x30-$-0x10,0xff db 0x40,0x41,0x42
The code section is only 18 bytes, so there should be enough room to fill 0xff until address 0x30, where the data shall be located. The "-2" make it look like that if the code size has something to do with the 0x10 in the expression. The "$" should be 18 (0x12), so the expression should result in 0x30 - 0x12 - 0x10 = 14 bytes to fill.
This also happens when the org is 0x100 and the code size is larger (> 256 bytes?).
I'm using the version 0.6.
Not sure about what happens internally, but I'm sure you'll be able to figure this out quickly
Keep up the good work!!!
Hey mi-chi,
As for your suggestion, yeah not supporting all those variants is a conscious decision. I like to have as much of a single canonical syntax as possible.
(On that note, already all the different hexadecimal literal syntaxes are bothering me. But I think those are an essential part of a lot of people’s code style preferences, and they wouldn’t want to use an assembler which didn’t support their favourite prefix, so I support them. Begrudgingly .)
However, I do want Glass to be flexible enough to allow people to define those aliases themselves.
E.g. today you can already write defb: equ db
I’m pretty sure, for ds
I’m not sure if it currently works due to Glass internals but you can give it a shot, and something like ex af,af
you currently can’t really define easily since there’s no real good way to do pattern matching and overloading with macros yet, but I think there is a convoluted way to do it.
So that’s the direction I’m looking to take.
As for the issue you describe, I don’t think it’s a bug but maybe I can improve documentation:
The $
context evaluates to the current logical address, which does take the org
into account. So in the bottom example, the value of $
is 22H
(not 12H), and 30H - 22H - 10H
is -2H
, a negative number. The way to pad up to logical address 30H would be ds 30H - $
. And if you would want to pad up to physical address 30H you could do ds 30H - ($ - 10H)
.
Thanks Grauw for your quick reply and the tip with the aliases.
There are so many assemblers with each having their own specific keywords, especially when they ship with linkers, to be able to define code and data segments and things alike. But they also differ quite much in the Z80 instruction syntax, e.g. some allow even to lazily write "sub a,5" or "add 5" - as opposed to the "official" Zilog specs. Those "dialects" are always a roadblock when changing assemblers. (And let's not even begin with the convoluted SDCC assembler's syntax - "ld e, 4 (ix)" instead of "ld e,(ix+4)").
I see about the relocation thing. That's interesting, I'm using Z80ASM from Z88DK for the Z80Runner, and had to write it the way I listed (which seems to use an absolute, 0-based address, disrespecting the origin), so when I simply threw the assembly file at your assembler, this hit me
Thanks for clarifying that.
That's interesting, I'm using Z80ASM from Z88DK for the Z80Runner, and had to write it the way I listed (which seems to use an absolute, 0-based address, disrespecting the origin)
I see, interesting, I think normally assemblers implement it the way Glass does. So in Z88DK’s Z80ASM you can’t write e.g. jp $
for an infinite loop?
oh wow, yeah, that behavior of z80asm/z88dk is very curious! I have looked at lots of assembler dialects when working on MDL, and all the ones I looked at (sjasm/sjasmplus/asmsx/tniasm/pasmo/glass/sdasz/macro80) behave like Glass.