Help with Assembly - DEFB, etc.

edited September 2014 in Development
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)
      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

  • edited September 2014
    Defb puts a byte value directly into memory, so you'd use it for defining byte variables or sometimes constant values like your string.

    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!
  • edited September 2014
    I think of DEFB as similar to a DATA statement in BASIC. If that's any help.
  • edited September 2014
    DEFB = Define Byte (8 Bit value) - mostly data for graphics, Sound and such stuff. INCBIN can be used in same way to include data from binary file.
    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.
  • edited September 2014
    I'll try to say it with another words

    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)
  • edited September 2014
    Ralf wrote: »
    But he apparently didn't want to count text length each time so he gets it by (TextEndAddress - TextStartAddress)
    He also saved one Byte to terminate the string.
  • edited September 2014
    Thank you all so much. It never ceases to amaze me the help that's available for this old machine.

    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.
  • edited September 2014
    Tobo wrote: »
    Can it be any length - could DEFB be followed by a short story for example, or is it limited?

    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
    DEFB 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0
    
    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.
    DEFB 0,0,0,0, 0,0,0,0
    DEFB 0,0,0,0, 0,0,0,0
    
    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.

    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 memory
    

    EQU is short of equals / equivalent and lot of assemblers use also '=' for same operation.

    For example this code fragments do very same thing:
    modify_me
     ld a, 255
     dec a
     ld (modify_me + 1), a
    
    modify_me = $ + 1
     ld a, 255
     dec a
     ld (modify_me), a
    
    modify_me .EQU $+1
     ld a, 255
     dec a
     ld (modify_me), a
    
  • edited September 2014
    I would say from my experience that using things like EQU isn't a necessity but rather a part of programming style. Personally I use it very rarely

    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
  • edited September 2014
    All these answers are so helpful to me. Thanks everyone.

    So, what effect does $ have by making it an effective constant of Eostr?
  • edited September 2014
    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:
    ORG 30000
    string defb 22,21,31,'!'
    eostr equ $

    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.
  • utzutz
    edited September 2014
    The "equ $" part is actually unnecessary in this example. You could simply put the "eostr" label in this place, with the same results. But some assemblers don't like labels at the end of the code, so that's probably why the "equ $" part is there.
  • edited September 2014
    Thank you, all.

    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.
  • edited September 2014
    30000,30001,30002,30003.

    ...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.
Sign In or Register to comment.