4

I have %rep preprocessor directive which creates a preprocessor loop. I would like to declare label in it, probably with some concatenation, but I cannot get the syntax right.

%assign i 0 
%rep    64 
   label_%i: ;this, of course, doesn't work
      inc rax    
%assign i i+1 
%endrep

So how to force NASM preprocessor to generate label_i for every "iteration"?

Rames
  • 918
  • 11
  • 27

2 Answers2

5

This can be accomplished by using the %+ notation. Here's an excerpt from the documentation:

4.1.4 Concatenating Single Line Macro Tokens: %+

Individual tokens in single line macros can be concatenated, to produce longer tokens for later processing. This can be useful if there are several similar macros that perform similar functions.

Please note that a space is required after %+, in order to disambiguate it from the syntax %+1 used in multiline macros.

More information on this and other features in the preprocessor can be found here.

David Hoelzer
  • 15,862
  • 4
  • 48
  • 67
2

If you don't need to reference the labels from outside the %rep block, the within-a-macro local %%label syntax can work:

%macro  jmpfwd 0
    times 21 nop
    jmp %%fwd                  ;;;;;   <<<------ This jump
    add ax, 0x1234    ; can this stall decoding?
;    lea eax, [ebx+edx+1]
  align 64
  %%fwd:                       ;;;;;   <<<------ jumps here
%endmacro

Then use that macro inside a %rep

    .looptop:
%rep 4
    jmpfwd
%endrep
; times 4 jmpfwd   nope, TIMES only works on (pseudo)instructions, not macros

    dec ecx
    jnz .looptop

(Turns out, Skylake can decode this without LCP stalls every iteration, only a few LCP stalls when the add hits the decoders in the same group as jmp before branch prediction for the unconditional jmp instructions take effect. The times 21 nop prevents it from fitting in the uop cache.)

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847