Help with Assembly - DEFB, etc.
Dear all,
I'm going through Jnathan Cauldwell's tutorial and find myself scratching my head at part I can't find a decent explanation of anywhere! Even Toni Baker has let me down.
In the following code, what does the eostr equ $ actually do? If I had to guess, it's doing some sort of LEN function (in this case = 1)
Also, I'd be grateful if someone could put into laymans terms, what DEFB and DEFW actually do and how one would use them.
Any help for this noob?
Tobo
I'm going through Jnathan Cauldwell's tutorial and find myself scratching my head at part I can't find a decent explanation of anywhere! Even Toni Baker has let me down.
In the following code, what does the eostr equ $ actually do? If I had to guess, it's doing some sort of LEN function (in this case = 1)
ld a,2 ; upper screen
call 5633 ; open channel
ld de,string ; address of string
ld bc,eostr-string ; length of string to print
call 8252 ; print our string
ret
string defb 22,21,31,'!'
eostr equ $
Also, I'd be grateful if someone could put into laymans terms, what DEFB and DEFW actually do and how one would use them.
Any help for this noob?
Tobo
Post edited by Tobo on
Comments
Defw does the same, but for 16-bit values, making sure to put them in the little endian format used by the Z80 - i.e. low byte first, high byte second.
Equ sets the value of a label to a fixed value. Looking at the code, I'd assume in that case the $ is a shorthand way of saying "the current address".
It's worth noting that assembler directives like these vary slightly between assemblers. There usually isn't that much difference, but it's the subtleties that catch you out!
DEFW = Define Word (16 Bit Value) - mostly used for fixed pointers.
DEFM = Define Message (alphanummeric) - For texts
DEFS = Define Space: Reserve a amount of Bytes e.g. for a buffer. (DEFS 1280 reserves 1280 Bytes).
And no, DEFM is not Define Memory and DEFS is not Define String.
When you write in assembler, let's say LD A,15 it will be replaced in Spectrum memory to 62,15
The same result you would get if you wrote DEFB 62,15. But it would be harder to read, wouldn't it? ;)
In Spectrum memory you can mix code and data all the time. It's your code flow which takes care that code isn't drawn to screen and data aren't executed.
By the way DEFB isn't Z80 command, it's assember command. Some assmeblers may use different command here like .BYTE and .WORD instead of DEFB and DEFW
As for your example code, Jonathan could write it easier:
ld a,2 ; upper screen call 5633 ; open channel ld de,string ; address of string ld bc,4 ; length of string to print call 8252 ; print our string ret string defb 22,21,31,'!'But he apparently didn't want to count text length each time so he gets it by (TextEndAddress - TextStartAddress)
I think I understand the above answers. The declarations simply highlight in Assembly that what follows is data of a chosen type - be they screen cords, or text, etc. Can it be any length - could DEFB be followed by a short story for example, or is it limited?
Also, I understand how Jonathan's used the Eostr label to get the 'end address', and therefore the length of the string he's printing, but why EQU $ ? I assume EQU is another Assembly only command but what does it do and why use a '$' - will this place 36 (the character code for $) in the relevant part of spectrum memory?
...I'm missing something here.
Depends on assembler you use, but every assembler I know allows quite lot of values. Probably everything you can find wil compile something like this In fact, some tools, like gfx editors, allows to export data in form text file with DEFB or DB directive. That indicates that DEFB directive is expected accomodate quite lot of data. Another thing is that coders tends to use shorter lines for better readability.
No, $ is just another operator, it could be named like "PLEASE_GIVE_ME_THE_CURRENT_ADDRESS_WHERE_THE_CODE_WILL_BE_COMPILED" for example. But it is long and back in times, editors had 32, 40 or 64 chars per line so shorter names are preffered.
Example:
.ORG 30000 ; $ will give 30000 here jr skip_data ; $ will give 30002 here as JR relative is two bytes long DEFB 0,1,2,3 ; $ will give 30006 here skip_data ; $ will give 30006 here - no output to memoryEQU is short of equals / equivalent and lot of assemblers use also '=' for same operation.
For example this code fragments do very same thing:
If you want to use it you must get a difference between
ORG 30000
Lives DEFB 5
and
ORG 30000
Lives EQU 5
In first case you reserve one memory cell at address 30000 and place value 5 into it then you can read it through LD A,(Lives) which is equal to LD A,5 (or any other value at this cell) or LD HL,Lives which means LD HL,30000. You can't do LD A,Lives here as you can't do LD A,30000. Lives is an address and Lives=30000
In second case EQU occupies 0 bytes after compilation. It works only at assembling level. Everywhere in the program where you use Lives it will be replaced to 5, you can think of it as a kind of constant. That's why you can place EQU declaration anywhere in your code. In such case you can do LD A,Lives which would mean LD A,5. Lives here is a constant value and Lives=5
So, what effect does $ have by making it an effective constant of Eostr?
$ as others said means current address
So if this data began let's say at 30000:
then $=30004 as there are 4 bytes before it at positions 30000,30001,30002,30003. This way:
string=30000
eostr=30004
And earlier you have instruction:
ld bc,eostr-string ; length of string to print
it becomes:
ld bc,30004-30000
and eventually
ld bc,4
If you check the compiled binary code, you will find there this "ld bc,4". All mentioned calculations were done during assembling and don't exist in the output.
I hear I do have a tendency of the need to be told things twice, but of course I ignore everyone that only tell me this once.
Thank you and please excuse my noobishness.
T.
...okay, I may have a few glasses of rum inside me, but bloody hell - that's dumbing down.
And it worked a treat. If the the dunce cap fits.....
Cheers, Ralf.
T.