Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make Conditional Assembly compatible with other cross-assemblers #103

Open
mvac7 opened this issue Jan 13, 2022 · 5 comments
Open

Make Conditional Assembly compatible with other cross-assemblers #103

mvac7 opened this issue Jan 13, 2022 · 5 comments

Comments

@mvac7
Copy link

mvac7 commented Jan 13, 2022

Hello asMSX team!

I am developing a routine that I would like to work with in the asMSX, Sjasm and tniASM cross-assemblers, but the peculiarities of defining constants and variables do not allow it, so I have gone to try to use conditional assembly.

While in Sjasm and tniASM they are compatible to a minimum, which allow the use of conditional assembly with this objective, in asMSX this is not fulfilled.

I would like to propose that this problem be discussed, thinking of facilitating the development of routines for common use without having to create and maintain several code files.

References:

2.6 Conditional Assembly

        Sometimes it's useful to have a certain piece of code assemble only
        when certain conditions are met. For instance when writing code for
        multiple platforms at the same time (Z80 and R800 for example), or
        for including/excluding debug code.
        tniASM provides this functionality through the IF-construct. Its
        basic form is:

        IF {operand} [{...}] [ELSE [{...}]] ENDIF

        Note that due to the multi-pass nature of tniASM, it's allowed to
        use forward references in IF-constructs. They may also be used
        accross source file boundaries. Ofcourse IF's can be nested with a
        practically infinite depth.

  2.6.1 IF {expression}
        The expression is evaluated and is considered 'false' when zero,
        while any non-zero result is considered 'true'.

        loop:   {...}
        IF $-loop < 128
          djnz loop
        ELSE
          dec b
          jp nz,loop
        ENDIF

  2.6.2 IFDEF {label}
        Check if a label was previously declared this pass.

        R800:           ; comment away for Z80 version
        IFDEF R800 mulub a,b ELSE call mulub_a_b ENDIF
        IFDEF R800 ELSE
        mulub_a_b: {...}
        ret
        ENDIF

  2.6.3 IFEXIST {string}
        Check if a file exists. Look at the second example for a nice
        trick, which works with any IF-instruction.

        IFEXIST "test" {...} ENDIF      ; do {...} if "test" exists
        IFEXIST "test" ELSE {...} ENDIF ; do {...} if "test" does not exist

  2.6.4 IFEXIST {label}
        Similar to IFDEF, but checks if a label exists regardless of where
        or when it is declared. You can use this to check if a label is
        declared further on in the source code.
@mvac7
Copy link
Author

mvac7 commented Jan 13, 2022

I have seen that the asMSX supports conditions written without parentheses (I have not seen it in the manual), so the compatibility problem is reduced.

If I have found a problem in the relational operator of equality.

In Sjasm they support both = and ==, while tniASM only supports = and asMSX supports ==.

A possible solution could be to add the equality operator = to asMSX.

It is worth highlighting, as a curiosity, in the not equal operator everyone supports !=, although in tniASM, it also supports <>.

References:

  • Sjasm 0.42 manual - Expressions - Operators
  • tniASM Guide Book:
2.4.1 Precedence Level 0 - Relational Operators
        
The relational operators are:

        x = y   equals
        x <> y  not equals
        x >< y   "    "
        x != y   "    "
        x < y   less than
        x > y   more than
        x <= y  less than or equals
        x =< y   "    "   "    "
        x >= y  more than or equals
        x => y   "    "   "    "

        Unlike in the C-language, the relational operators use -1 for 'true'
        and 0 for 'false' (in stead of 1 and 0). This way there's no need
        for boolean versions of the AND, OR and XOR operators, since they
        work in exactly the same way as the bitwise ones.
        The relational operators allow for complex expressions such as:
        x*(1+2*(x<0))

        which gives the absolute value of 'x'.

@duhow
Copy link
Collaborator

duhow commented Jan 23, 2022

I don't think it's a good idea to use a single = to compare, as it can lead to confusion.

@mvac7
Copy link
Author

mvac7 commented Jan 24, 2022

@duhow I agree with you. I have continued to study this topic and I don't think it offers any improvement.

But I found a way, while listening to The Social Network soundtrack ;)

I share it here in case it would be useful for someone who has the same need.

If you add in the main code a Label that marks the name of the assembler (ASMSX, SJASM or TNIASM) and/or the runtime environment (MSXROM, MSXDOS or MSXBASIC), you can use IFDEF to add differences, although there is an exception: for Sjasm IFDEF doesn't work with Labels, it works with macros. For this case it would be necessary to add a 'DEFINE' plus the label.

Although all this at the moment will not work with asMSX until issue #90 is solved

For asMSX and tniASM:

;This label allows you to distinguish the assembler,
;when you need it when using conditional assembly
;Labels: ASMSX , SJASM or TNIASM
;Use it with the IFDEF statement
ASMSX:

;This label allows you to distinguish the runtime environment,
;when you need it when using conditional assembly
;Labels: MSXROM , MSXDOS or MSXBASIC
;Use it with the IFDEF statement
MSXROM:

For Sjasm:

;This label allows you to distinguish the assembler,
;when you need it when using conditional assembly
;Labels: ASMSX , SJASM or TNIASM
;Use it with the IFDEF statement
DEFINE SJASM

;This label allows you to distinguish the runtime environment,
;when you need it when using conditional assembly
;Labels: MSXROM , MSXDOS or MSXBASIC
;Use it with the IFDEF statement
DEFINE MSXROM

Example of a conditional assembler use case:

IFDEF MSXDOS
    LD    HL,$002D              ;MSXID3=BIOS System constant (MSX version number)
    LD    A,[$FCC1]             ;EXPTBL=main BIOS-ROM slot address
    CALL  $000C                 ;RDSLT=Reads the value of an address in another slot
    EI                          ;RDSLT leaves interrupts disabled                        
ELSE
    ld    A,[$002D]             ;MSXID3=BIOS System constant (MSX version number)
ENDIF

duhow added a commit that referenced this issue Jan 30, 2022
This allows to use IFDEF ASMSX in order to perform specific actions in
asMSX.

Relates to #103
duhow added a commit that referenced this issue Jan 30, 2022
This allows to use IFDEF ASMSX in order to perform specific actions in
asMSX.

Relates to #103
@duhow
Copy link
Collaborator

duhow commented Jan 30, 2022

Having #108 to define ASMSX in program, you should be able to use it for specific actions to do in ASMSX.
Feel free to provide any feedback or additional commits there.

@Fubukimaru
Copy link
Owner

With #90 fixed, this should be already ok and we can close it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants