Search code examples
assemblyx86macrosnasmgnu-assembler

How to get the value of a variable in a macro argument


Working code in NASM assembly is the following:

%macro ISR_NOERRCODE 1
    [GLOBAL isr%1]
    isr%1:
        ...
%endmacro

%assign i 0             ; Initialize the loop Variable

%rep 8
    ISR_NOERRCODE i
    %assign i i+1
%endrep

Which expands into 8 code blocks name isr1, isr2, etc. But in GAS syntax, the argument given to the macro does not seem to expand. My code is:

.macro ISR_NOERRCODE n
    .global isr\n
    isr\n:
        ...
.endm

.set i, 0

.rept
    ISR_NOERRCODE $i
    .set i, $i + 1
.endr

Which results in an assembler error:

Error: symbol `isr$i' is already defined

Because the macro seems to be taking the $i argument as a literal string.

Is this even possible in GAS syntax?


Solution

  • The first thing is that you'll need to use the .altmacro directive to enable alternate macro mode. One of the added features is:

    Expression results as strings

    You can write %expr to evaluate the expression expr and use the result as a string.

    So if we prepend our macro argument with a % it will be evaluated as an expression and turned into a string, which is what we want here. Your code could look like:

    .altmacro
    
    .macro ISR_NOERRCODE n
        .global isr\n
        isr\n:
             ...
    
    .set i, 0 
    .rept 8
        ISR_NOERRCODE %i
        .set i, i + 1 
    .endr
    

    Conversely you can disable alternate macro mode with .noaltmacro which is the default.