Shop OBEX P1 Docs P2 Docs Learn Events
Assembler IFDEF / IFNDEF question — Parallax Forums

Assembler IFDEF / IFNDEF question

pjvpjv Posts: 1,903
edited 2008-01-26 02:40 in General Discussion
Hi All;

I'm needing some conditional assembly statements in a macro to effect the following:

············ If a LABEL has NOT already been defined, then define it (along with some code), else do not re-define it.

So when I define a macro like

Assign· Macro· Addr
···· ········· IFNDEF Addr
Addr············· somecode
········· ···· ENDIF
·········· Endm

Then the first time I invoke the macro with:
··········
··· ······ code1
······· ·· code2
····· ···· Assign· Name
········· ·code3
······· ·· code4

I would expect to get

······· ·· code1
····· ···· code2
Name····somecode
····· ···· code3
········· ·code4

Instead, the assembler appears not to·generate the macro's code as it believes the label ADDR is already assigned.·Using the opposite, IFDEF instead of the IFNDEF, generates the same result.

Am I mis-understanding the application of IFDEF and IFNDEF ?? or is this a bug.

Can anyone help me here, it is not·well explained in the documents.

Cheers,

Peter (pjv)

Comments

  • James NewtonJames Newton Posts: 329
    edited 2008-01-22 03:38
    I believe the problem is that "Name" gets evaluated to a numerical value prior to being passed to the macro. Name evaluates to 0 which is then the value assigned to ADDR and so ADDR is defined, but it is defined as 0 so it isn't a valid definition and both ways fail. Try this:

    Assign Macro Addr
    what = Addr
    EndM

    then watch the listing to see whats value.

    What you are trying to do is pass the TEXT "Name" that is "N" "a" "m" "e" and the macro parameter system doesn't get that. The OLD SASM, prior to the SXKey IDE, passed all parameters as text then evaluated them after expanding the macro. Or passed them as values if you put "?" in front of them.

    I could be wrong... It's been years since I've looked at this stuff.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    ---
    James Newton, Host of SXList.com
    james at sxlist,com 1-619-652-0593 fax:1-208-279-8767
    SX FAQ / Code / Tutorials / Documentation:
    http://www.sxlist.com Pick faster!



  • pjvpjv Posts: 1,903
    edited 2008-01-22 06:10
    Hi James;

    So I've tried:

    Device SX28, oschs3
    IRC_SLOW
    Freq 50 MHz

    Assign·Macro Addr································· ;create an entry in an indirect jump table
    ·············· local MacroAddr···················· · ;try with a local variable
    ·············· MacroAddr = Addr··················· ;force a valuation
    ······················ ifndef MacroAddr········· ···;test for Addr already existing
    ······························ MainAddr = $········ ·;no, so remember where we came from
    ······························ org TableEnd········· ;append to the end of the jump table
    I??Maddr···················page·MacroAddr······;the indirect entry in the jump table
    ··························· ···jmp·MacroAddr······· ;a single indirect paged entry to the desired address in main
    ··························· ···TableEnd = $······· ··;update table end
    ·······························org·MainAddr········· ;restore Main address
    ···················· ··endif·························· ··;end of if
    ·············· endm··································· ;end of macro

    ····················· ·org·$10
    TableEnd·= $

    Main················ org·$50
    ······················ mov·w,#1···················· ·;arbitrary code
    ····················· ·Assign·There················· ;create indirect entry via the macro if not already existing
    There············· ·mov·w,#2··················· ··;more arbitrary code
    ····················· ·mov·w,#3····················· ;more arbitrary code
    ··················· · ·Assign·There················· ;assign again, but it should not perform this by skipping past it with the ifndef directive in the macro
    ····················· ·mov·w,#3···················· ·;more arbitrary code


    and I can't get it to cooperate. Even if I force the value to be passed using the ? operator.

    Would you mind having a poke at this for me ?

    What I'm trying to do is to use a macro to create an indirect jump table, and have multiple references to any address use only a single entry in the table.

    Cheers,

    Peter (pjv)

    Post Edited (pjv) : 1/22/2008 6:24:33 AM GMT
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2008-01-22 06:46
    pjv,
    Here is a macro from my dynamic library. Whenever I use macros I always look
    back into that file as it demonstrates the most useful macro possibilities.

    _lib_queue_var··macro·name, size
    · tempsize = size+2
    if ((data + tempsize - 1) & $F0) != (data & $F0)
    error "queue buffer too large, crossing rambank boundary"
    endif
    ifndef vp_queue
    vp_queue
    endif
    ···org·data
    expand
    ??name??··equ·$
    queue_??name??_sizenum·ds·1
    queue_??name??_headtail·ds·1
    queue_??name??_buffer·ds·size
    noexpand
    data··=·$
    endm

    The key here is to use the parameter, enclosed in ??
    in your case that would be
    ??addr??

    I attached my file so you can inspect the generated listing as well.

    regards peter
  • James NewtonJames Newton Posts: 329
    edited 2008-01-23 00:39
    What PV said.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    ---
    James Newton, Host of SXList.com
    james at sxlist,com 1-619-652-0593 fax:1-208-279-8767
    SX FAQ / Code / Tutorials / Documentation:
    http://www.sxlist.com Pick faster!



  • pjvpjv Posts: 1,903
    edited 2008-01-25 16:02
    OK Guys, I must be dense or something, because I just can't get it to work no matter what I do. Using the pasting operator, ....setting labels in the first column or second column.... evaluatins variables, assigning values.... just nothing .

    In its simplest form, all I'm trying to do is: If an instruction statement starting with a particular label has not yet been entered into my source code (that is a proper use of "IFNDEF" of the lable as I understand it), then create the line, otherwise do nothing and exit the macro.

    Like:

    Assign··· macro Name············ ;create a macro
    ················· ifdef I??Name····· ;test for the modified parameter passed already exists
    ············ exitm····················· ;if so then bail out
    ············ else······················· ;otherwise
    I??Name······· jmp Name········· ;create this label from the parameter passed
    ············ endm····················· ;done

    And when I invoke the macro once, this works OK. It's when I invoke it subsequent times that I get a "redefine symbol" message. What I need the macro to realize it has already issued the statement in the first instance, and from that point on it should not attempt to issu it again. This way I could create a very nice jump table sort of automatically.

    I just can't get it to be happy after the first invocation...... help??

    Cheers,

    Peter (pjv)
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2008-01-25 16:54
    Try this:

    Assign··· macro Name············ ;create a macro
    ················· ifdef I??Name??····· ;test for the modified parameter passed already exists
    ············ exitm····················· ;if so then bail out
    ············ else······················· ;otherwise
    I??Name??······· jmp ??Name??········· ;create this label from the parameter passed
    ············ endm····················· ;done


    regards peter
  • pjvpjv Posts: 1,903
    edited 2008-01-25 17:18
    Hi Peter;

    Yes, I have literally copied your post and imported into SX and it does not work.
    Also, I believe the trailing set of pasting operator (??) is of no consequence as it has nothing to concatenate to.

    AAARRRGGGG!!

    Cheers,

    Peter (pjv)
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2008-01-25 17:46
    pjv,
    Attached program generates this listing:

    ···· 1· 07F8· 0F7F····· device········· SX28,oschs1,turbo,stackx,optionx······· ;sx device options
    ···· 2· =00000000······ irc_cal········ IRC_SLOW
    ···· 3· =02FAF080······ freq··········· 50_000_000····························· ;cpu frequency
    ···· 4· 07FF· 0A07····· reset·········· main
    ···· 5·················
    ···· 6················· Assign· macro·· Name··········· ;create a macro
    ···· 7···················· ifndef I??Name??············ ;test for the modified parameter passed already exists
    ···· 8················· I??Name??
    ···· 9························· jmp···· @??Name??······ ;create this label from the parameter passed
    ··· 10···················· endif
    ··· 11················· endm··························· ;done
    ··· 12·················
    ··· 13· =00000000·············· org 0
    ··· 14················· Assign rx1
    ··· 15·············· m···· ifndef Irx1········· ;test for the modified parameter passed already exists
    ··· 16·············· m· Irx1
    ··· 17·············· m········· jmp···· @rx1··· ;create this label from the parameter passed
    ··· 18·············· m···· endif
    ··· 20················· Assign rx2
    ··· 21·············· m···· ifndef Irx2········· ;test for the modified parameter passed already exists
    ··· 22·············· m· Irx2
    ··· 23·············· m········· jmp···· @rx2··· ;create this label from the parameter passed
    ··· 24·············· m···· endif
    ··· 26· =00000004······ rx1
    ··· 27· 0000· 0C01············· mov···· w,#1
    ··· 28· =00000005······ rx2
    ··· 29· 0001· 01C4············· add···· w,fsr
    ··· 30· 0002· 000C············· ret
    ··· 31· =00000007······ main
    ··· 32· 0003· 0A07············· jmp···· main

    Cross Reference
    10 symbols

    Symbol··························· Type·· Value····· Line
    __SASM··························· DATA·· 00000001·· 0000
    __SX_FREQ························ DATA·· 02FAF080·· 0003
    __SX_IRC_CAL····················· DATA·· 00000000·· 0002
    __SX_RESET······················· RESB·· 00000A07·· 0004
    fsr······························ RESV·· 00000004·· 0029
    Irx1····························· ADDR·· 00000000·· 0016
    Irx2····························· ADDR·· 00000002·· 0022
    main····························· ADDR·· 00000007·· 0031
    rx1······························ ADDR·· 00000004·· 0026
    rx2······························ ADDR·· 00000005·· 0028

    According to the symbol table, Irx1 and Irx2 are created at the right addresses.

    regards peter
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2008-01-25 18:39
    I think I know what is going wrong.
    Look at this listing

    ···· 1· 07F8· 0F7F····· device········· SX28,oschs1,turbo,stackx,optionx······· ;sx device options
    ···· 2· =00000000······ irc_cal········ IRC_SLOW
    ···· 3· =02FAF080······ freq··········· 50_000_000····························· ;cpu frequency
    ···· 4· 07FF· 0A05····· reset·········· main
    ···· 5················· expand
    ···· 6·················
    ···· 7················· Assign2 macro·· Name··········· ;create a macro
    ···· 8················· ifndef I??Name
    ···· 9························· org···· $
    ··· 10················· I??Name
    ··· 11························· jmp···· @Name·· ;create this label from the parameter passed
    ··· 12················· else
    ··· 13························· org···· $
    ··· 14················· endif
    ··· 15················· endm··························· ;done
    ··· 16·················
    ··· 17················· Assign· macro·· Name··········· ;create a macro
    ··· 18················· ifndef I??Name········· ;test for the modified parameter passed already exists
    ··· 19················· I??Name
    ··· 20························· jmp···· @??Name ;create this label from the parameter passed
    ··· 21················· endif
    ··· 22················· endm··························· ;done
    ··· 23·················
    ··· 24· =00000000·············· org 0
    ··· 25················· ;Assign rx1
    ··· 26················· ;Assign rx2
    ··· 27················· Assign2 rx1
    ··· 28·············· m· ifndef Irx1
    ··· 29·············· m········· org···· $
    ··· 30·············· m· Irx1
    ··· 31·············· m········· jmp···· @rx1··· ;create this label from the parameter passed
    ··· 32·············· m· else
    ··· 33· =00000000··· m········· org···· $
    ··· 34·············· m· endif
    ··· 36· =00000002······ rx1
    ··· 37· 0000· 0C01············· mov···· w,#1
    ··· 38· =00000003······ rx2
    ··· 39· 0001· 01C4············· add···· w,fsr
    ··· 40· 0002· 000C············· ret
    ··· 41· =00000005······ main
    ··· 42· 0003· 0A05············· jmp···· main

    Cross Reference
    9 symbols

    Symbol··························· Type·· Value····· Line
    __SASM··························· DATA·· 00000001·· 0000
    __SX_FREQ························ DATA·· 02FAF080·· 0003
    __SX_IRC_CAL····················· DATA·· 00000000·· 0002
    __SX_RESET······················· RESB·· 00000A05·· 0004
    fsr······························ RESV·· 00000004·· 0039
    Irx1····························· ADDR·· 00000000·· 0030
    main····························· ADDR·· 00000005·· 0041
    rx1······························ ADDR·· 00000002·· 0036
    rx2······························ ADDR·· 00000003·· 0038

    The label Irx1 does not exist when calling Assign2, so it gets created (but no code).
    On the second pass the label exist and the·else clause is executed (does generate code).


    regards peter
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2008-01-25 18:48
    So the trick is to insert identical code in both 'if' section and 'else' section,
    but the label only in the 'if' section, and an org in the 'else' section.

    ···· 1· 07F8· 0F7F····· device········· SX28,oschs1,turbo,stackx,optionx······· ;sx device options
    ···· 2· =00000000······ irc_cal········ IRC_SLOW
    ···· 3· =02FAF080······ freq··········· 50_000_000····························· ;cpu frequency
    ···· 4· 07FF· 0A07····· reset·········· main
    ···· 5················· expand
    ···· 6·················
    ···· 7················· Assign· macro·· Name··········· ;create a macro
    ···· 8················· ifndef I??Name········· ;test for the modified parameter passed already exists
    ···· 9················· I??Name
    ··· 10························· jmp···· @??Name ;create this label from the parameter passed
    ··· 11················· else
    ··· 12························· org···· I??Name
    ··· 13························· jmp···· @??Name ;create this label from the parameter passed
    ··· 14················· endif
    ··· 15················· endm··························· ;done
    ··· 16·················
    ··· 17· =00000000·············· org 0
    ··· 18················· Assign rx1
    ··· 19·············· m· ifndef Irx1············ ;test for the modified parameter passed already exists
    ··· 20·············· m· Irx1
    ··· 21·············· m········· jmp···· @rx1··· ;create this label from the parameter passed
    ··· 22·············· m· else
    ··· 23· =00000000··· m········· org···· Irx1
    ··· 24· 0000· 0010·· m········· jmp···· @rx1··· ;create this label from the parameter passed
    ······· 0001· 0A04
    ··· 25·············· m· endif
    ··· 27················· Assign rx2
    ··· 28·············· m· ifndef Irx2············ ;test for the modified parameter passed already exists
    ··· 29·············· m· Irx2
    ··· 30·············· m········· jmp···· @rx2··· ;create this label from the parameter passed
    ··· 31·············· m· else
    ··· 32· =00000002··· m········· org···· Irx2
    ··· 33· 0002· 0010·· m········· jmp···· @rx2··· ;create this label from the parameter passed
    ······· 0003· 0A05
    ··· 34·············· m· endif
    ··· 36· =00000004······ rx1
    ··· 37· 0004· 0C01············· mov···· w,#1
    ··· 38· =00000005······ rx2
    ··· 39· 0005· 01C4············· add···· w,fsr
    ··· 40· 0006· 000C············· ret
    ··· 41· =00000007······ main
    ··· 42· 0007· 0A07············· jmp···· main

    Cross Reference
    10 symbols

    Symbol··························· Type·· Value····· Line
    __SASM··························· DATA·· 00000001·· 0000
    __SX_FREQ························ DATA·· 02FAF080·· 0003
    __SX_IRC_CAL····················· DATA·· 00000000·· 0002
    __SX_RESET······················· RESB·· 00000A07·· 0004
    fsr······························ RESV·· 00000004·· 0039
    Irx1····························· ADDR·· 00000000·· 0020
    Irx2····························· ADDR·· 00000002·· 0029
    main····························· ADDR·· 00000007·· 0041
    rx1······························ ADDR·· 00000004·· 0036
    rx2······························ ADDR·· 00000005·· 0038

    regards peter
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2008-01-25 19:52
    This is it. You can call Assign with identical names from different locations,
    but the entry is only generated once.

    ···· 1· 07F8· 0F7F····· device········· SX28,oschs1,turbo,stackx,optionx······· ;sx device options
    ···· 2· =00000000······ irc_cal········ IRC_SLOW
    ···· 3· =02FAF080······ freq··········· 50_000_000····························· ;cpu frequency
    ···· 4· 07FF· 0A07····· reset·········· main
    ···· 5················· expand
    ···· 6·················
    ···· 7· =00000000······ Irx1value = 0·· ;define variables for possible labels
    ···· 8· =00000000······ Irx2value = 0
    ···· 9·················
    ··· 10················· Assign· macro·· Name··········· ;create a macro
    ··· 11················· if I??Name??value == 0
    ··· 12················· I??Name??value = 1············· ;prevent multiples
    ··· 13················· I??Name
    ··· 14························· jmp···· @??Name ;create this label from the parameter passed
    ··· 15················· endif
    ··· 16················· endm··························· ;done
    ··· 17·················
    ··· 18· =00000000·············· org 0
    ··· 19················· Assign rx1
    ··· 20·············· m· if Irx1value == 0
    ··· 21· =00000001··· m· Irx1value = 1·········· ;prevent multiples
    ··· 22· =00000000··· m· Irx1
    ··· 23· 0000· 0010·· m········· jmp···· @rx1··· ;create this label from the parameter passed
    ······· 0001· 0A04
    ··· 24·············· m· endif
    ··· 26················· Assign rx2
    ··· 27·············· m· if Irx2value == 0
    ··· 28· =00000001··· m· Irx2value = 1·········· ;prevent multiples
    ··· 29· =00000002··· m· Irx2
    ··· 30· 0002· 0010·· m········· jmp···· @rx2··· ;create this label from the parameter passed
    ······· 0003· 0A05
    ··· 31·············· m· endif
    ··· 33················· Assign rx1····· ;create entry from 2nd location
    ··· 34·············· m· if Irx1value == 0
    ··· 35·············· m· Irx1value = 1·········· ;prevent multiples
    ··· 36·············· m· Irx1
    ··· 37·············· m········· jmp···· @rx1··· ;create this label from the parameter passed
    ··· 38·············· m· endif
    ··· 40·················
    ··· 41· =00000004······ rx1
    ··· 42· 0004· 0C01············· mov···· w,#1
    ··· 43· =00000005······ rx2
    ··· 44· 0005· 01C4············· add···· w,fsr
    ··· 45· 0006· 000C············· ret
    ··· 46· =00000007······ main
    ··· 47· 0007· 0A07············· jmp···· main
    ··· 48·················

    Cross Reference
    12 symbols

    Symbol··························· Type·· Value····· Line
    __SASM··························· DATA·· 00000001·· 0000
    __SX_FREQ························ DATA·· 02FAF080·· 0003
    __SX_IRC_CAL····················· DATA·· 00000000·· 0002
    __SX_RESET······················· RESB·· 00000A07·· 0004
    fsr······························ RESV·· 00000004·· 0044
    Irx1····························· ADDR·· 00000000·· 0022
    Irx1value························· VAR·· 00000001·· 0007
    Irx2····························· ADDR·· 00000002·· 0029
    Irx2value························· VAR·· 00000001·· 0008
    main····························· ADDR·· 00000007·· 0046
    rx1······························ ADDR·· 00000004·· 0041
    rx2······························ ADDR·· 00000005·· 0043

    The idea is to create compile variables for each possible label, initialized to 0.
    Inside Assign, those variables will be set to 1, so a second call with an identical name
    does not generate code.

    regards peter
  • pjvpjv Posts: 1,903
    edited 2008-01-25 20:08
    Hi Peter;

    No, that still does not work. Perhaps I'm not explaining myself well enough.

    I wish to create a macro (several in fact, one for indirect jump, one for indirect call, and one for indirect statejump, and perhaps more) that I will name IJump, ICall etc.

    These macros will each have one parameter; the label of the address were the jump is to end up. What the macro is to do, is test for a modified label (that would be the·name·of the entry in the jump table), particularly IPARAM where the parameter passed to the macro is pre-pended with something to differentiate it from the target jump address (so address FOUR is modified to IFOUR), and if that label does not exist, then append an entry in the jump table on page zero for address FOUR passed to the macro IJump. Each entry in the table has the modified target name as a label with a page and the jump address of the target. Naturally the macro needs to restore the program counter with an org to the value it had at the point of the macro call.

    I can get this to work for the first instance I make the macro call to any target address, but subsequent calls to the SAME address will not work. Naturally I wish to have only one entry in my jump table per jump location, but be able to access that multiple times, and from anywhere.

    So my issue is the multiple call situation. At present (that is without this feature) I have to manually remember whether or not the indirect entry has already been entered, and I thought the macro should be able to do this for me.

    Thanks for your interest, and putting up with my ranting.

    Cheers,

    Peter (pjv)

    Post Edited (pjv) : 1/25/2008 8:14:46 PM GMT
  • James NewtonJames Newton Posts: 329
    edited 2008-01-25 22:47
    PJV, I've already done all that in the mymacros.src file I referenced above. Look at the way the subroutine macro is defined. The only difference is you do the setup when you define the subroutine rather than when you call it; that way you don't have to worry about duplicate setup.

    There is also a working macro for the OLD version of SASM that includes a subroutine inline the first time and then calls it at that location each following time in the old newsletter article.

    It's fun to see new people work with macros though...

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    ---
    James Newton, Host of SXList.com
    james at sxlist,com 1-619-652-0593 fax:1-208-279-8767
    SX FAQ / Code / Tutorials / Documentation:
    http://www.sxlist.com Pick faster!



  • pjvpjv Posts: 1,903
    edited 2008-01-26 02:40
    Hi James;

    I've looked through all that and was quite overwhelmed.... not sure I can grasp it all, and to know the nuances. You've done a tremendous amount of work.

    However, I thought my question was quite simple (perhaps the answer is not) and I'd like to approach it in the manner I've described if at all possible, because not having to pre-think the macro instances will lend itself better to the RTOS where I plan to use this.

    If you could lend a hand in that direction it would be appreciated, or at least tell me if it can't be done that way.

    In the mean time I will try to see where I can find "the old newsletter article", and an OLD verson of SASM.

    Cheers,

    Peter (pjv)
Sign In or Register to comment.