[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


https://bugzilla.nasm.us/show_bug.cgi?id=3392837

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
start:
  ...
end:
%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
start:
  times 26 db 0
end:

%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:
https://hg.pushbx.org/ecm/ldebug/file/b167070fdcc5/source/debug.asm#l246

%define CODESECTIONOFFSET
(100h+ldebug_data_entry_size+asmtable1_size+asmtable2_size)
%define INITSECTIONOFFSET
(CODESECTIONOFFSET+ldebug_code_size+ldebug_code2_size)


Here's something similar but with conversion to a different unit and back:
https://hg.pushbx.org/ecm/ldebug/file/b167070fdcc5/source/debug.asm#l265

%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:
https://hg.pushbx.org/ecm/lmacros/file/99b01fa65007/lmacros1.mac#l213

%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
scalars:
https://hg.pushbx.org/ecm/ldebug/file/b167070fdcc5/source/debug.asm#l357

        add ax, paras(INITSECTIONOFFSET)
        push ax
        push bx
        retf


Here's a bit that declares an equate called init_size:
https://hg.pushbx.org/ecm/ldebug/file/b167070fdcc5/source/debug.asm#l7188

        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):
https://hg.pushbx.org/ecm/ldebug/file/b167070fdcc5/source/debug.asm#l7223

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

        numdef SHOWINITSIZE, _DEFAULTSHOWSIZE
%if _SHOWINITSIZE
%warning init segment holds __INITSIZE bytes
%endif

-- 
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