Simple Z80ASM question

ZX80, ZX 81, ZX Spectrum, TS2068 and other clones
Post Reply
TobyLobster
New member
Posts: 3
Joined: Sun May 08, 2022 3:41 pm

Simple Z80ASM question

Post by TobyLobster »

I'm new in these parts, so I'm doing something wrong I'm sure. Source test.asm file:

Code: Select all

ORG $1234

.start
    RET
    DW start

IF start == 0
    DB "Hello"
ENDIF
I'm assembling with:

Code: Select all

Z88DK-Z80ASM -mz80 -b -s -l -m -g test.asm
I would have expected "Hello" not to appear in the output binary, but it does:

Code: Select all

c9 34 12 48 65 6c 6c 6f

Shouldn't "start" be $1234? I would have expected the IF to evaluate to false, and no "Hello" to be output.
The map file shows start=$1234 as expected.
The listing file shows the addresses starting at zero, and the "DW start" as listed as two zero bytes.
The symbols file shows start=$0000.

Any ideas?
User avatar
jorgegv
Well known member
Posts: 287
Joined: Wed Nov 18, 2020 5:08 pm

Re: Simple Z80ASM question

Post by jorgegv »

I think the explanation is he following:

start is a label, so it is resolved at link time. This means it is set to 0 at compile time and its address noted for later resolving after code has been relocated to its final position. So at compilation time your code checks for start == 0, it finds it is true and emits the DB code.

A way to achieve what you want could be the following:

Code: Select all

DEFC MY_ORG_ADDRESS = $1234

ORG MY_ORG_ADDRESS

.start
    RET
    DW start

IF MY_ORG_ADDRESS == 0
    DB "Hello"
ENDIF
The addresses in the listing file are relative to the start of the compilation module, that is, the file you are compiling. They always start at 0 at the beginning of the file. The final address for "start" is determined at link time, and is output in the map file.
TobyLobster
New member
Posts: 3
Joined: Sun May 08, 2022 3:41 pm

Re: Simple Z80ASM question

Post by TobyLobster »

Thanks for that explanation @jorgegv. In general 'start' and MY_ORG_ADDRESS may not be the same. I think I can use "MY_ORG_ADDRESS + start" to get the actual resolved address of start, which is a bit clunky.

To back your theory up, the documentation does say that ORG is for the linker. It seems misleading to the point of being a bug to (a) output a listing file showing the wrong bytes and (b) output a symbol file with the wrong value for the symbols! I've never seen that in other assemblers I've used, and it doesn't seem useful behaviour.

Another workaround is to wrap all the code in a PHASE $1234 ... DEPHASE instead of the ORG then all works as expected. i.e. labels can be resolved correctly at compile time using PHASE. So why not with ORG? Is this expected but perhaps non-standard behaviour for ORG?

I want to ASSERT on the value of a label being the value I think it should be, but current behaviour makes it clunky when using ORG.
Post Reply