[Nasm-bugs] [Bug 3392837] %eval(pointer) can't expand in %warning/%error and %eval documentation typos

noreply-nasm at dev.nasm.us noreply-nasm at dev.nasm.us
Tue Mar 7 08:48:03 PST 2023


C. Masloch <pushbx at ulukai.org> changed:

           What    |Removed                     |Added
                 CC|                            |pushbx at ulukai.org

--- Comment #3 from C. Masloch <pushbx at ulukai.org> ---
4.11 should not be changed unnecessarily as the %assign way works with older
NASM versions whereas %eval(...) does not.

Other than that, I believe the canonical way to expand things in
%warning/%error/%fatal is to use %assign to a temporary single-line macro. This
works in older NASM versions as well, if the expression being assigned
evaluates to a scalar.

%eval($) and %assign foo $ both do not work, as the dollar-sign refers to a
relocatable symbol, not a scalar. To obtain a scalar you can do label
arithmetic with a section start label to obtain a label delta, possibly adding
a displacement to simulate the section start offset. For example:

  org 256
%assign size_smacro end - start + 256

Using an equate is also possible:

size_equate equ end - start + 256

But this won't on its own expand to a number in the preprocessor. However, you
can feed the equate (if it's done with the proper label arithmetic to be a
scalar) into %assign after the fact:

%assign size_equate_smacro size_equate

Resulting in the complete test case like this:

$ nasm -v
NASM version 2.16rc0 compiled on Sep  5 2022
$ cat test.asm 

  org 256
  times 26 db 0

%assign size_smacro end - start + 256
size_equate equ end - start + 256
%assign size_equate_smacro size_equate

%warning size_smacro size_equate size_equate_smacro
$ nasm test.asm 
test.asm:11: warning: 282 size_equate 282 [-w+user]

The label arithmetic is the same as needed to divide or shift a label delta (or
sum of label deltas), which is not allowed by NASM for non-scalar values. For
example, to gain a resident size in paragraphs you could use an expression for
an assembly operand like in:

  mov dx, (resident_end - resident_start + 256 + 15) / 16

This is a related but somewhat separate problem to usage with %assign, but the
solution is similar. It's just that %assign additionally allows to propagate
scalar values back to the preprocessor from the assembler; note that this makes
the build fail if running in preprocess-only mode (switch -E).

As the NASM developers have oft repeated, the -f bin output format is
conceptually a linker internal to the NASM executable, so the assembler or
preprocessor part don't know that %eval($) is a "pointer value" (offset,
actually) that "should be known". It is simply a relocatable symbol value, that
the assembler/preprocessor cannot evaluate as a scalar.

For examples of label arithmetic, I'll refer to my application, lDebug.

Here's some defines that add several sections' sizes:


Here's something similar but with conversion to a different unit and back:

%define BOOTDELTA       (fromkib(kib(auxbuff_size * 2 \
                                + historysegment_size \
                                + datastack_size \
                                + INITSECTIONOFFSET + 16)))

The single-line macros used here are from lmacros1.mac and use shifting to
convert between units, which is only allowed for scalars. Source:

%idefine paras(b)       ((b)+15>>4)
%idefine pages(b)       ((b)+511>>9)
%idefine kib(b)         ((b)+1023>>10)
%idefine fromkib(k)             ((k)<<10)

Here's how to use one of the above defines, using one of the lmacros1 macros
yet again to shift so that another unit is calculated, also allowed only for

        add ax, paras(INITSECTIONOFFSET)
        push ax
        push bx

Here's a bit that declares an equate called init_size:

        usesection INIT
                align 16, db 0
init_size       equ $-section.INIT.vstart
        endarea init, 1

Finally, here's how to use the init_size equate with %assign and %warning (plus
an %if numeric conditional expression):

%assign __INITSIZE init_size
%if __INITSIZE > (64 * 1024)
 %error init segment too large (%[__INITSIZE])

%warning init segment holds __INITSIZE bytes

You are receiving this mail because:
You are watching all bug changes.
You are on the CC list for the bug.

More information about the Nasm-bugs mailing list