The Netwide Assembler: NASM

Next Chapter | Previous Chapter | Contents | Index

Chapter 4: The NASM Preprocessor

NASM contains a powerful macro processor, which supports conditional assembly, multi-level file inclusion, two forms of macro (single-line and multi-line), and a `context stack' mechanism for extra macro power. Preprocessor directives all begin with a % sign.

The preprocessor collapses all lines which end with a backslash (\) character into a single line. Thus:

%define THIS_VERY_LONG_MACRO_NAME_IS_DEFINED_TO \ 
        THIS_VALUE

will work like a single-line macro without the backslash-newline sequence.

4.1 Single-Line Macros

4.1.1 The Normal Way: %define

Single-line macros are defined using the %define preprocessor directive. The definitions work in a similar way to C; so you can do things like

%define ctrl    0x1F & 
%define param(a,b) ((a)+(a)*(b)) 

        mov     byte [param(2,ebx)], ctrl 'D'

which will expand to

        mov     byte [(2)+(2)*(ebx)], 0x1F & 'D'

When the expansion of a single-line macro contains tokens which invoke another macro, the expansion is performed at invocation time, not at definition time. Thus the code

%define a(x)    1+b(x) 
%define b(x)    2*x 

        mov     ax,a(8)

will evaluate in the expected way to mov ax,1+2*8, even though the macro b wasn't defined at the time of definition of a.

Macros defined with %define are case sensitive: after %define foo bar, only foo will expand to bar: Foo or FOO will not. By using %idefine instead of %define (the `i' stands for `insensitive') you can define all the case variants of a macro at once, so that %idefine foo bar would cause foo, Foo, FOO, fOO and so on all to expand to bar.

There is a mechanism which detects when a macro call has occurred as a result of a previous expansion of the same macro, to guard against circular references and infinite loops. If this happens, the preprocessor will only expand the first occurrence of the macro. Hence, if you code

%define a(x)    1+a(x) 

        mov     ax,a(3)

the macro a(3) will expand once, becoming 1+a(3), and will then expand no further. This behaviour can be useful: see section 8.1 for an example of its use.

You can overload single-line macros: if you write

%define foo(x)   1+x 
%define foo(x,y) 1+x*y

the preprocessor will be able to handle both types of macro call, by counting the parameters you pass; so foo(3) will become 1+3 whereas foo(ebx,2) will become 1+ebx*2. However, if you define

%define foo bar

then no other definition of foo will be accepted: a macro with no parameters prohibits the definition of the same name as a macro with parameters, and vice versa.

This doesn't prevent single-line macros being redefined: you can perfectly well define a macro with

%define foo bar

and then re-define it later in the same source file with

%define foo baz

Then everywhere the macro foo is invoked, it will be expanded according to the most recent definition. This is particularly useful when defining single-line macros with %assign (see section 4.1.6).

You can pre-define single-line macros using the `-d' option on the NASM command line: see section 2.1.18.

4.1.2 Enhancing %define: %xdefine

To have a reference to an embedded single-line macro resolved at the time that it is embedded, as opposed to when the calling macro is expanded, you need a different mechanism to the one offered by %define. The solution is to use %xdefine, or it's case-insensitive counterpart %ixdefine.

Suppose you have the following code:

%define  isTrue  1 
%define  isFalse isTrue 
%define  isTrue  0 

val1:    db      isFalse 

%define  isTrue  1 

val2:    db      isFalse

In this case, val1 is equal to 0, and val2 is equal to 1. This is because, when a single-line macro is defined using %define, it is expanded only when it is called. As isFalse expands to isTrue, the expansion will be the current value of isTrue. The first time it is called that is 0, and the second time it is 1.

If you wanted isFalse to expand to the value assigned to the embedded macro isTrue at the time that isFalse was defined, you need to change the above code to use %xdefine.

%xdefine isTrue  1 
%xdefine isFalse isTrue 
%xdefine isTrue  0 

val1:    db      isFalse 

%xdefine isTrue  1 

val2:    db      isFalse

Now, each time that isFalse is called, it expands to 1, as that is what the embedded macro isTrue expanded to at the time that isFalse was defined.

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

As an example, consider the following:

%define BDASTART 400h                ; Start of BIOS data area

struc   tBIOSDA                      ; its structure 
        .COM1addr       RESW    1 
        .COM2addr       RESW    1 
        ; ..and so on 
endstruc

Now, if we need to access the elements of tBIOSDA in different places, we can end up with:

        mov     ax,BDASTART + tBIOSDA.COM1addr 
        mov     bx,BDASTART + tBIOSDA.COM2addr

This will become pretty ugly (and tedious) if used in many places, and can be reduced in size significantly by using the following macro:

; Macro to access BIOS variables by their names (from tBDA):

%define BDA(x)  BDASTART + tBIOSDA. %+ x

Now the above code can be written as:

        mov     ax,BDA(COM1addr) 
        mov     bx,BDA(COM2addr)

Using this feature, we can simplify references to a lot of macros (and, in turn, reduce typing errors).

4.1.4 The Macro Name Itself: %? and %??

The special symbols %? and %?? can be used to reference the macro name itself inside a macro expansion, this is supported for both single-and multi-line macros. %? refers to the macro name as invoked, whereas %?? refers to the macro name as declared. The two are always the same for case-sensitive macros, but for case-insensitive macros, they can differ.

For example:

%idefine Foo mov %?,%?? 

        foo 
        FOO

will expand to:

        mov foo,Foo 
        mov FOO,Foo

The sequence:

%idefine keyword $%?

can be used to make a keyword "disappear", for example in case a new instruction has been used as a label in older code. For example:

%idefine pause $%?                  ; Hide the PAUSE instruction

4.1.5 Undefining Macros: %undef

Single-line macros can be removed with the %undef command. For example, the following sequence:

%define foo bar 
%undef  foo 

        mov     eax, foo

will expand to the instruction mov eax, foo, since after %undef the macro foo is no longer defined.

Macros that would otherwise be pre-defined can be undefined on the command-line using the `-u' option on the NASM command line: see section 2.1.19.

4.1.6 Preprocessor Variables: %assign

An alternative way to define single-line macros is by means of the %assign command (and its case-insensitive counterpart %iassign, which differs from %assign in exactly the same way that %idefine differs from %define).

%assign is used to define single-line macros which take no parameters and have a numeric value. This value can be specified in the form of an expression, and it will be evaluated once, when the %assign directive is processed.

Like %define, macros defined using %assign can be re-defined later, so you can do things like

%assign i i+1

to increment the numeric value of a macro.

%assign is useful for controlling the termination of %rep preprocessor loops: see section 4.5 for an example of this. Another use for %assign is given in section 7.4 and section 8.1.

The expression passed to %assign is a critical expression (see section 3.8), and must also evaluate to a pure number (rather than a relocatable reference such as a code or data address, or anything involving a register).

4.1.7 Defining Strings: %defstr

%defstr, and its case-insensitive counterpart %idefstr, define or redefine a single-line macro without parameters but converts the entire right-hand side, after macro expansion, to a quoted string before definition.

For example:

%defstr test TEST

is equivalent to

%define test 'TEST'

This can be used, for example, with the %! construct (see section 4.10.2):

%defstr PATH %!PATH		; The operating system PATH variable

4.2 String Handling in Macros: %strlen and %substr

It's often useful to be able to handle strings in macros. NASM supports two simple string handling macro operators from which more complex operations can be constructed.

4.2.1 String Length: %strlen

The %strlen macro is like %assign macro in that it creates (or redefines) a numeric value to a macro. The difference is that with %strlen, the numeric value is the length of a string. An example of the use of this would be:

%strlen charcnt 'my string'

In this example, charcnt would receive the value 9, just as if an %assign had been used. In this example, 'my string' was a literal string but it could also have been a single-line macro that expands to a string, as in the following example:

%define sometext 'my string' 
%strlen charcnt sometext

As in the first case, this would result in charcnt being assigned the value of 9.

4.2.2 Sub-strings: %substr

Individual letters in strings can be extracted using %substr. An example of its use is probably more useful than the description:

%substr mychar 'xyzw' 1       ; equivalent to %define mychar 'x' 
%substr mychar 'xyzw' 2       ; equivalent to %define mychar 'y' 
%substr mychar 'xyzw' 3       ; equivalent to %define mychar 'z' 
%substr mychar 'xyzw' 2,2     ; equivalent to %define mychar 'yz' 
%substr mychar 'xyzw' 2,-1    ; equivalent to %define mychar 'yzw' 
%substr mychar 'xyzw' 2,-2    ; equivalent to %define mychar 'yz'

As with %strlen (see section 4.2.1), the first parameter is the single-line macro to be created and the second is the string. The third parameter specifies the first character to be selected, and the optional fourth parameter preceeded by comma) is the length. Note that the first index is 1, not 0 and the last index is equal to the value that %strlen would assign given the same string. Index values out of range result in an empty string. A negative length means "until N-1 characters before the end of string", i.e. -1 means until end of string, -2 until one character before, etc.

4.3 Multi-Line Macros: %macro

Multi-line macros are much more like the type of macro seen in MASM and TASM: a multi-line macro definition in NASM looks something like this.

%macro  prologue 1 

        push    ebp 
        mov     ebp,esp 
        sub     esp,%1 

%endmacro

This defines a C-like function prologue as a macro: so you @, then it does nothing to the local label mechanism. So you could code

label1:                         ; a non-local label 
.local:                         ; this is really label1.local 
..@foo:                         ; this is a special symbol 
label2:                         ; another non-local label 
.local:                         ; this is really label2.local 

        jmp     ..@foo          ; this will jump three lines up

NASM has the capacity to define other special symbols beginning with a double period: for example, ..start is used to specify the entry point in the obj output format (see section 6.2.6).

Next Chapter | Previous Chapter | Contents | Index ./usr/share/doc/nasm/html/nasmdoc4.html0000644000000000000000000023650211026070423016674 0ustar rootrootNASM Manual

The Netwide Assembler: NASM

Next Chapter | Previous Chapter | Contents | Index

Chapter 4: The NASM Preprocessor

NASM contains a powerful macro processor, which supports conditional assembly, multi-level file inclusion, two forms of macro (single-line and multi-line), and a `context stack' mechanism for extra macro power. Preprocessor directives all begin with a % sign.

The preprocessor collapses all lines which end with a backslash (\) character into a single line. Thus:

%define THIS_VERY_LONG_MACRO_NAME_IS_DEFINED_TO \ 
        THIS_VALUE

will work like a single-line macro without the backslash-newline sequence.

4.1 Single-Line Macros

4.1.1 The Normal Way: %define

Single-line macros are defined using the %define preprocessor directive. The definitions work in a similar way to C; so you can do things like

%define ctrl    0x1F & 
%define param(a,b) ((a)+(a)*(b)) 

        mov     byte [param(2,ebx)], ctrl 'D'

which will expand to

        mov     byte [(2)+(2)*(ebx)], 0x1F & 'D'

When the expansion of a single-line macro contains tokens which invoke another macro, the expansion is performed at invocation time, not at definition time. Thus the code

%define a(x)    1+b(x) 
%define b(x)    2*x 

        mov     ax,a(8)

will evaluate in the expected way to mov ax,1+2*8, even though the macro b wasn't defined at the time of definition of a.

Macros defined with %define are case sensitive: after %define foo bar, only foo will expand to bar: Foo or FOO will not. By using %idefine instead of %define (the `i' stands for `insensitive') you can define all the case variants of a macro at once, so that %idefine foo bar would cause foo, Foo, FOO, fOO and so on all to expand to bar.

There is a mechanism which detects when a macro call has occurred as a result of a previous expansion of the same macro, to guard against circular references and infinite loops. If this happens, the preprocessor will only expand the first occurrence of the macro. Hence, if you code

%define a(x)    1+a(x) 

        mov     ax,a(3)

the macro a(3) will expand once, becoming 1+a(3), and will then expand no further. This behaviour can be useful: see section 8.1 for an example of its use.

You can overload single-line macros: if you write

%define foo(x)   1+x 
%define foo(x,y) 1+x*y

the preprocessor will be able to handle both types of macro call, by counting the parameters you pass; so foo(3) will become 1+3 whereas foo(ebx,2) will become 1+ebx*2. However, if you define

%define foo bar

then no other definition of foo will be accepted: a macro with no parameters prohibits the definition of the same name as a macro with parameters, and vice versa.

This doesn't prevent single-line macros being redefined: you can perfectly well define a macro with

%define foo bar

and then re-define it later in the same source file with

%define foo baz

Then everywhere the macro foo is invoked, it will be expanded according to the most recent definition. This is particularly useful when defining single-line macros with %assign (see section 4.1.6).

You can pre-define single-line macros using the `-d' option on the NASM command line: see section 2.1.18.

4.1.2 Enhancing %define: %xdefine

To have a reference to an embedded single-line macro resolved at the time that it is embedded, as opposed to when the calling macro is expanded, you need a different mechanism to the one offered by %define. The solution is to use %xdefine, or it's case-insensitive counterpart %ixdefine.

Suppose you have the following code:

%define  isTrue  1 
%define  isFalse isTrue 
%define  isTrue  0 

val1:    db      isFalse 

%define  isTrue  1 

val2:    db      isFalse

In this case, val1 is equal to 0, and val2 is equal to 1. This is because, when a single-line macro is defined using %define, it is expanded only when it is called. As isFalse expands to isTrue, the expansion will be the current value of isTrue. The first time it is called that is 0, and the second time it is 1.

If you wanted isFalse to expand to the value assigned to the embedded macro isTrue at the time that isFalse was defined, you need to change the above code to use %xdefine.

%xdefine isTrue  1 
%xdefine isFalse isTrue 
%xdefine isTrue  0 

val1:    db      isFalse 

%xdefine isTrue  1 

val2:    db      isFalse

Now, each time that isFalse is called, it expands to 1, as that is what the embedded macro isTrue expanded to at the time that isFalse was defined.

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

As an example, consider the following:

%define BDASTART 400h                ; Start of BIOS data area

struc   tBIOSDA                      ; its structure 
        .COM1addr       RESW    1 
        .COM2addr       RESW    1 
        ; ..and so on 
endstruc

Now, if we need to access the elements of tBIOSDA in different places, we can end up with:

        mov     ax,BDASTART + tBIOSDA.COM1addr 
        mov     bx,BDASTART + tBIOSDA.COM2addr

This will become pretty ugly (and tedious) if used in many places, and can be reduced in size significantly by using the following macro:

; Macro to access BIOS variables by their names (from tBDA):

%define BDA(x)  BDASTART + tBIOSDA. %+ x

Now the above code can be written as:

        mov     ax,BDA(COM1addr) 
        mov     bx,BDA(COM2addr)

Using this feature, we can simplify references to a lot of macros (and, in turn, reduce typing errors).

4.1.4 The Macro Name Itself: %? and %??

The special symbols %? and %?? can be used to reference the macro name itself inside a macro expansion, this is supported for both single-and multi-line macros. %? refers to the macro name as invoked, whereas %?? refers to the macro name as declared. The two are always the same for case-sensitive macros, but for case-insensitive macros, they can differ.

For example:

%idefine Foo mov %?,%?? 

        foo 
        FOO

will expand to:

        mov foo,Foo 
        mov FOO,Foo

The sequence:

%idefine keyword $%?

can be used to make a keyword "disappear", for example in case a new instruction has been used as a label in older code. For example:

%idefine pause $%?                  ; Hide the PAUSE instruction

4.1.5 Undefining Macros: %undef

Single-line macros can be removed with the %undef command. For example, the following sequence:

%define foo bar 
%undef  foo 

        mov     eax, foo

will expand to the instruction mov eax, foo, since after %undef the macro foo is no longer defined.

Macros that would otherwise be pre-defined can be undefined on the command-line using the `-u' option on the NASM command line: see section 2.1.19.

4.1.6 Preprocessor Variables: %assign

An alternative way to define single-line macros is by means of the %assign command (and its case-insensitive counterpart %iassign, which differs from %assign in exactly the same way that %idefine differs from %define).

%assign is used to define single-line macros which take no parameters and have a numeric value. This value can be specified in the form of an expression, and it will be evaluated once, when the %assign directive is processed.

Like %define, macros defined using %assign can be re-defined later, so you can do things like

%assign i i+1

to increment the numeric value of a macro.

%assign is useful for controlling the termination of %rep preprocessor loops: see section 4.5 for an example of this. Another use for %assign is given in section 7.4 and section 8.1.

The expression passed to %assign is a critical expression (see section 3.8), and must also evaluate to a pure number (rather than a relocatable reference such as a code or data address, or anything involving a register).

4.1.7 Defining Strings: %defstr

%defstr, and its case-insensitive counterpart %idefstr, define or redefine a single-line macro without parameters but converts the entire right-hand side, after macro expansion, to a quoted string before definition.

For example:

%defstr test TEST

is equivalent to

%define test 'TEST'

This can be used, for example, with the %! construct (see section 4.10.2):

%defstr PATH %!PATH		; The operating system PATH variable

4.2 String Handling in Macros: %strlen and %substr

It's often useful to be able to handle strings in macros. NASM supports two simple string handling macro operators from which more complex operations can be constructed.

4.2.1 String Length: %strlen

The %strlen macro is like %assign macro in that it creates (or redefines) a numeric value to a macro. The difference is that with %strlen, the numeric value is the length of a string. An example of the use of this would be:

%strlen charcnt 'my string'

In this example, charcnt would receive the value 9, just as if an %assign had been used. In this example, 'my string' was a literal string but it could also have been a single-line macro that expands to a string, as in the following example:

%define sometext 'my string' 
%strlen charcnt sometext

As in the first case, this would result in charcnt being assigned the value of 9.

4.2.2 Sub-strings: %substr

Individual letters in strings can be extracted using %substr. An example of its use is probably more useful than the description:

%substr mychar 'xyzw' 1       ; equivalent to %define mychar 'x' 
%substr mychar 'xyzw' 2       ; equivalent to %define mychar 'y' 
%substr mychar 'xyzw' 3       ; equivalent to %define mychar 'z' 
%substr mychar 'xyzw' 2,2     ; equivalent to %define mychar 'yz' 
%substr mychar 'xyzw' 2,-1    ; equivalent to %define mychar 'yzw' 
%substr mychar 'xyzw' 2,-2    ; equivalent to %define mychar 'yz'

As with %strlen (see section 4.2.1), the first parameter is the single-line macro to be created and the second is the string. The third parameter specifies the first character to be selected, and the optional fourth parameter preceeded by comma) is the length. Note that the first index is 1, not 0 and the last index is equal to the value that %strlen would assign given the same string. Index values out of range result in an empty string. A negative length means "until N-1 characters before the end of string", i.e. -1 means until end of string, -2 until one character before, etc.

4.3 Multi-Line Macros: %macro

Multi-line macros are much more like the type of macro seen in MASM and TASM: a multi-line macro definition in NASM looks something like this.

%macro  prologue 1 

        push    ebp 
        mov     ebp,esp 
        sub     esp,%1 

%endmacro

This defines a C-like function prologue as a macro: so you @, then it does nothing to the local label mechanism. So you could code

label1:                         ; a non-local label 
.local:                         ; this is really label1.local 
..@foo:                         ; this is a special symbol 
label2:                         ; another non-local label 
.local:                         ; this is really label2.local 

        jmp     ..@foo          ; this will jump three lines up

NASM has the capacity to define other special symbols beginning with a double period: for example, ..start is used to specify the entry point in the obj output format (see section 6.2.6).

Next Chapter | Previous Chapter | Contents | Index ./usr/share/doc/nasm/html/nasmdoc4.html0000644000000000000000000023650211026070423016674 0ustar rootrootNASM Manual

The Netwide Assembler: NASM

Next Chapter | Previous Chapter | Contents | Index

Chapter 4: The NASM Preprocessor

NASM contains a powerful macro processor, which supports conditional assembly, multi-level file inclusion, two forms of macro (single-line and multi-line), and a `context stack' mechanism for extra macro power. Preprocessor directives all begin with a % sign.

The preprocessor collapses all lines which end with a backslash (\) character into a single line. Thus:

%define THIS_VERY_LONG_MACRO_NAME_IS_DEFINED_TO \ 
        THIS_VALUE

will work like a single-line macro without the backslash-newline sequence.

4.1 Single-Line Macros

4.1.1 The Normal Way: %define

Single-line macros are defined using the %define preprocessor directive. The definitions work in a similar way to C; so you can do things like

%define ctrl    0x1F & 
%define param(a,b) ((a)+(a)*(b)) 

        mov     byte [param(2,ebx)], ctrl 'D'

which will expand to

        mov     byte [(2)+(2)*(ebx)], 0x1F & 'D'

When the expansion of a single-line macro contains tokens which invoke another macro, the expansion is performed at invocation time, not at definition time. Thus the code

%define a(x)    1+b(x) 
%define b(x)    2*x 

        mov     ax,a(8)

will evaluate in the expected way to mov ax,1+2*8, even though the macro b wasn't defined at the time of definition of a.

Macros defined with %define are case sensitive: after %define foo bar, only foo will expand to bar: Foo or FOO will not. By using %idefine instead of %define (the `i' stands for `insensitive') you can define all the case variants of a macro at once, so that %idefine foo bar would cause foo, Foo, FOO, fOO and so on all to expand to bar.

There is a mechanism which detects when a macro call has occurred as a result of a previous expansion of the same macro, to guard against circular references and infinite loops. If this happens, the preprocessor will only expand the first occurrence of the macro. Hence, if you code

%define a(x)    1+a(x) 

        mov     ax,a(3)

the macro a(3) will expand once, becoming 1+a(3), and will then expand no further. This behaviour can be useful: see section 8.1 for an example of its use.

You can overload single-line macros: if you write

%define foo(x)   1+x 
%define foo(x,y) 1+x*y

the preprocessor will be able to handle both types of macro call, by counting the parameters you pass; so foo(3) will become 1+3 whereas foo(ebx,2) will become 1+ebx*2. However, if you define

%define foo bar

then no other definition of foo will be accepted: a macro with no parameters prohibits the definition of the same name as a macro with parameters, and vice versa.

This doesn't prevent single-line macros being redefined: you can perfectly well define a macro with

%define foo bar

and then re-define it later in the same source file with

%define foo baz

Then everywhere the macro foo is invoked, it will be expanded according to the most recent definition. This is particularly useful when defining single-line macros with %assign (see section 4.1.6).

You can pre-define single-line macros using the `-d' option on the NASM command line: see section 2.1.18.

4.1.2 Enhancing %define: %xdefine

To have a reference to an embedded single-line macro resolved at the time that it is embedded, as opposed to when the calling macro is expanded, you need a different mechanism to the one offered by %define. The solution is to use %xdefine, or it's case-insensitive counterpart %ixdefine.

Suppose you have the following code:

%define  isTrue  1 
%define  isFalse isTrue 
%define  isTrue  0 

val1:    db      isFalse 

%define  isTrue  1 

val2:    db      isFalse

In this case, val1 is equal to 0, and val2 is equal to 1. This is because, when a single-line macro is defined using %define, it is expanded only when it is called. As isFalse expands to isTrue, the expansion will be the current value of isTrue. The first time it is called that is 0, and the second time it is 1.

If you wanted isFalse to expand to the value assigned to the embedded macro isTrue at the time that isFalse was defined, you need to change the above code to use %xdefine.

%xdefine isTrue  1 
%xdefine isFalse isTrue 
%xdefine isTrue  0 

val1:    db      isFalse 

%xdefine isTrue  1 

val2:    db      isFalse

Now, each time that isFalse is called, it expands to 1, as that is what the embedded macro isTrue expanded to at the time that isFalse was defined.

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

As an example, consider the following:

%define BDASTART 400h                ; Start of BIOS data area

struc   tBIOSDA                      ; its structure 
        .COM1addr       RESW    1 
        .COM2addr       RESW    1 
        ; ..and so on 
endstruc

Now, if we need to access the elements of tBIOSDA in different places, we can end up with:

        mov     ax,BDASTART + tBIOSDA.COM1addr 
        mov     bx,BDASTART + tBIOSDA.COM2addr

This will become pretty ugly (and tedious) if used in many places, and can be reduced in size significantly by using the following macro:

; Macro to access BIOS variables by their names (from tBDA):

%define BDA(x)  BDASTART + tBIOSDA. %+ x

Now the above code can be written as:

        mov     ax,BDA(COM1addr) 
        mov     bx,BDA(COM2addr)

Using this feature, we can simplify references to a lot of macros (and, in turn, reduce typing errors).

4.1.4 The Macro Name Itself: %? and %??

The special symbols %? and %?? can be used to reference the macro name itself inside a macro expansion, this is supported for both single-and multi-line macros. %? refers to the macro name as invoked, whereas %?? refers to the macro name as declared. The two are always the same for case-sensitive macros, but for case-insensitive macros, they can differ.

For example:

%idefine Foo mov %?,%?? 

        foo 
        FOO

will expand to:

        mov foo,Foo 
        mov FOO,Foo

The sequence:

%idefine keyword $%?

can be used to make a keyword "disappear", for example in case a new instruction has been used as a label in older code. For example:

%idefine pause $%?                  ; Hide the PAUSE instruction

4.1.5 Undefining Macros: %undef

Single-line macros can be removed with the %undef command. For example, the following sequence:

%define foo bar 
%undef  foo 

        mov     eax, foo

will expand to the instruction mov eax, foo, since after %undef the macro foo is no longer defined.

Macros that would otherwise be pre-defined can be undefined on the command-line using the `-u' option on the NASM command line: see section 2.1.19.

4.1.6 Preprocessor Variables: %assign

An alternative way to define single-line macros is by means of the %assign command (and its case-insensitive counterpart %iassign, which differs from %assign in exactly the same way that %idefine differs from %define).

%assign is used to define single-line macros which take no parameters and have a numeric value. This value can be specified in the form of an expression, and it will be evaluated once, when the %assign directive is processed.

Like %define, macros defined using %assign can be re-defined later, so you can do things like

%assign i i+1

to increment the numeric value of a macro.

%assign is useful for controlling the termination of %rep preprocessor loops: see section 4.5 for an example of this. Another use for %assign is given in section 7.4 and section 8.1.

The expression passed to %assign is a critical expression (see section 3.8), and must also evaluate to a pure number (rather than a relocatable reference such as a code or data address, or anything involving a register).

4.1.7 Defining Strings: %defstr

%defstr, and its case-insensitive counterpart %idefstr, define or redefine a single-line macro without parameters but converts the entire right-hand side, after macro expansion, to a quoted string before definition.

For example:

%defstr test TEST

is equivalent to

%define test 'TEST'

This can be used, for example, with the %! construct (see section 4.10.2):

%defstr PATH %!PATH		; The operating system PATH variable

4.2 String Handling in Macros: %strlen and %substr

It's often useful to be able to handle strings in macros. NASM supports two simple string handling macro operators from which more complex operations can be constructed.

4.2.1 String Length: %strlen

The %strlen macro is like %assign macro in that it creates (or redefines) a numeric value to a macro. The difference is that with %strlen, the numeric value is the length of a string. An example of the use of this would be:

%strlen charcnt 'my string'

In this example, charcnt would receive the value 9, just as if an %assign had been used. In this example, 'my string' was a literal string but it could also have been a single-line macro that expands to a string, as in the following example:

%define sometext 'my string' 
%strlen charcnt sometext

As in the first case, this would result in charcnt being assigned the value of 9.

4.2.2 Sub-strings: %substr

Individual letters in strings can be extracted using %substr. An example of its use is probably more useful than the description:

%substr mychar 'xyzw' 1       ; equivalent to %define mychar 'x' 
%substr mychar 'xyzw' 2       ; equivalent to %define mychar 'y' 
%substr mychar 'xyzw' 3       ; equivalent to %define mychar 'z' 
%substr mychar 'xyzw' 2,2     ; equivalent to %define mychar 'yz' 
%substr mychar 'xyzw' 2,-1    ; equivalent to %define mychar 'yzw' 
%substr mychar 'xyzw' 2,-2    ; equivalent to %define mychar 'yz'

As with %strlen (see section 4.2.1), the first parameter is the single-line macro to be created and the second is the string. The third parameter specifies the first character to be selected, and the optional fourth parameter preceeded by comma) is the length. Note that the first index is 1, not 0 and the last index is equal to the value that %strlen would assign given the same string. Index values out of range result in an empty string. A negative length means "until N-1 characters before the end of string", i.e. -1 means until end of string, -2 until one character before, etc.

4.3 Multi-Line Macros: %macro

Multi-line macros are much more like the type of macro seen in MASM and TASM: a multi-line macro definition in NASM looks something like this.

%macro  prologue 1 

        push    ebp 
        mov     ebp,esp 
        sub     esp,%1 

%endmacro

This defines a C-like function prologue as a macro: so you @, then it does nothing to the local label mechanism. So you could code

label1:                         ; a non-local label 
.local:                         ; this is really label1.local 
..@foo:                         ; this is a special symbol 
label2:                         ; another non-local label 
.local:                         ; this is really label2.local 

        jmp     ..@foo          ; this will jump three lines up

NASM has the capacity to define other special symbols beginning with a double period: for example, ..start is used to specify the entry point in the obj output format (see section 6.2.6).

Next Chapter | Previous Chapter | Contents | Index ./usr/share/doc/nasm/html/nasmdoc4.html0000644000000000000000000023650211026070423016674 0ustar rootrootNASM Manual

The Netwide Assembler: NASM

Next Chapter | Previous Chapter | Contents | Index

Chapter 4: The NASM Preprocessor

NASM contains a powerful macro processor, which supports conditional assembly, multi-level file inclusion, two forms of macro (single-line and multi-line), and a `context stack' mechanism for extra macro power. Preprocessor directives all begin with a % sign.

The preprocessor collapses all lines which end with a backslash (\) character into a single line. Thus:

%define THIS_VERY_LONG_MACRO_NAME_IS_DEFINED_TO \ 
        THIS_VALUE

will work like a single-line macro without the backslash-newline sequence.

4.1 Single-Line Macros

4.1.1 The Normal Way: %define

Single-line macros are defined using the %define preprocessor directive. The definitions work in a similar way to C; so you can do things like

%define ctrl    0x1F & 
%define param(a,b) ((a)+(a)*(b)) 

        mov     byte [param(2,ebx)], ctrl 'D'

which will expand to

        mov     byte [(2)+(2)*(ebx)], 0x1F & 'D'

When the expansion of a single-line macro contains tokens which invoke another macro, the expansion is performed at invocation time, not at definition time. Thus the code

%define a(x)    1+b(x) 
%define b(x)    2*x 

        mov     ax,a(8)

will evaluate in the expected way to mov ax,1+2*8, even though the macro b wasn't defined at the time of definition of a.

Macros defined with %define are case sensitive: after %define foo bar, only foo will expand to bar: Foo or FOO will not. By using %idefine instead of %define (the `i' stands for `insensitive') you can define all the case variants of a macro at once, so that %idefine foo bar would cause foo, Foo, FOO, fOO and so on all to expand to bar.

There is a mechanism which detects when a macro call has occurred as a result of a previous expansion of the same macro, to guard against circular references and infinite loops. If this happens, the preprocessor will only expand the first occurrence of the macro. Hence, if you code

%define a(x)    1+a(x) 

        mov     ax,a(3)

the macro a(3) will expand once, becoming 1+a(3), and will then expand no further. This behaviour can be useful: see section 8.1 for an example of its use.

You can overload single-line macros: if you write

%define foo(x)   1+x 
%define foo(x,y) 1+x*y

the preprocessor will be able to handle both types of macro call, by counting the parameters you pass; so foo(3) will become 1+3 whereas foo(ebx,2) will become 1+ebx*2. However, if you define

%define foo bar

then no other definition of foo will be accepted: a macro with no parameters prohibits the definition of the same name as a macro with parameters, and vice versa.

This doesn't prevent single-line macros being redefined: you can perfectly well define a macro with

%define foo bar

and then re-define it later in the same source file with

%define foo baz

Then everywhere the macro foo is invoked, it will be expanded according to the most recent definition. This is particularly useful when defining single-line macros with %assign (see section 4.1.6).

You can pre-define single-line macros using the `-d' option on the NASM command line: see section 2.1.18.

4.1.2 Enhancing %define: %xdefine

To have a reference to an embedded single-line macro resolved at the time that it is embedded, as opposed to when the calling macro is expanded, you need a different mechanism to the one offered by %define. The solution is to use %xdefine, or it's case-insensitive counterpart %ixdefine.

Suppose you have the following code:

%define  isTrue  1 
%define  isFalse isTrue 
%define  isTrue  0 

val1:    db      isFalse 

%define  isTrue  1 

val2:    db      isFalse

In this case, val1 is equal to 0, and val2 is equal to 1. This is because, when a single-line macro is defined using %define, it is expanded only when it is called. As isFalse expands to isTrue, the expansion will be the current value of isTrue. The first time it is called that is 0, and the second time it is 1.

If you wanted isFalse to expand to the value assigned to the embedded macro isTrue at the time that isFalse was defined, you need to change the above code to use %xdefine.

%xdefine isTrue  1 
%xdefine isFalse isTrue 
%xdefine isTrue  0 

val1:    db      isFalse 

%xdefine isTrue  1 

val2:    db      isFalse

Now, each time that isFalse is called, it expands to 1, as that is what the embedded macro isTrue expanded to at the time that isFalse was defined.

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

As an example, consider the following:

%define BDASTART 400h                ; Start of BIOS data area

struc   tBIOSDA                      ; its structure 
        .COM1addr       RESW    1 
        .COM2addr       RESW    1 
        ; ..and so on 
endstruc

Now, if we need to access the elements of tBIOSDA in different places, we can end up with:

        mov     ax,BDASTART + tBIOSDA.COM1addr 
        mov     bx,BDASTART + tBIOSDA.COM2addr

This will become pretty ugly (and tedious) if used in many places, and can be reduced in size significantly by using the following macro:

; Macro to access BIOS variables by their names (from tBDA):

%define BDA(x)  BDASTART + tBIOSDA. %+ x

Now the above code can be written as:

        mov     ax,BDA(COM1addr) 
        mov     bx,BDA(COM2addr)

Using this feature, we can simplify references to a lot of macros (and, in turn, reduce typing errors).

4.1.4 The Macro Name Itself: %? and %??

The special symbols %? and %?? can be used to reference the macro name itself inside a macro expansion, this is supported for both single-and multi-line macros. %? refers to the macro name as invoked, whereas %?? refers to the macro name as declared. The two are always the same for case-sensitive macros, but for case-insensitive macros, they can differ.

For example:

%idefine Foo mov %?,%?? 

        foo 
        FOO

will expand to:

        mov foo,Foo 
        mov FOO,Foo

The sequence:

%idefine keyword $%?

can be used to make a keyword "disappear", for example in case a new instruction has been used as a label in older code. For example:

%idefine pause $%?                  ; Hide the PAUSE instruction

4.1.5 Undefining Macros: %undef

Single-line macros can be removed with the %undef command. For example, the following sequence:

%define foo bar 
%undef  foo 

        mov     eax, foo

will expand to the instruction mov eax, foo, since after %undef the macro foo is no longer defined.

Macros that would otherwise be pre-defined can be undefined on the command-line using the `-u' option on the NASM command line: see section 2.1.19.

4.1.6 Preprocessor Variables: %assign

An alternative way to define single-line macros is by means of the %assign command (and its case-insensitive counterpart %iassign, which differs from %assign in exactly the same way that %idefine differs from %define).

%assign is used to define single-line macros which take no parameters and have a numeric value. This value can be specified in the form of an expression, and it will be evaluated once, when the %assign directive is processed.

Like %define, macros defined using %assign can be re-defined later, so you can do things like

%assign i i+1

to increment the numeric value of a macro.

%assign is useful for controlling the termination of %rep preprocessor loops: see section 4.5 for an example of this. Another use for %assign is given in section 7.4 and section 8.1.

The expression passed to %assign is a critical expression (see section 3.8), and must also evaluate to a pure number (rather than a relocatable reference such as a code or data address, or anything involving a register).

4.1.7 Defining Strings: %defstr

%defstr, and its case-insensitive counterpart %idefstr, define or redefine a single-line macro without parameters but converts the entire right-hand side, after macro expansion, to a quoted string before definition.

For example:

%defstr test TEST

is equivalent to

%define test 'TEST'

This can be used, for example, with the %! construct (see section 4.10.2):

%defstr PATH %!PATH		; The operating system PATH variable

4.2 String Handling in Macros: %strlen and %substr

It's often useful to be able to handle strings in macros. NASM supports two simple string handling macro operators from which more complex operations can be constructed.

4.2.1 String Length: %strlen

The %strlen macro is like %assign macro in that it creates (or redefines) a numeric value to a macro. The difference is that with %strlen, the numeric value is the length of a string. An example of the use of this would be:

%strlen charcnt 'my string'

In this example, charcnt would receive the value 9, just as if an %assign had been used. In this example, 'my string' was a literal string but it could also have been a single-line macro that expands to a string, as in the following example:

%define sometext 'my string' 
%strlen charcnt sometext

As in the first case, this would result in charcnt being assigned the value of 9.

4.2.2 Sub-strings: %substr

Individual letters in strings can be extracted using %substr. An example of its use is probably more useful than the description:

%substr mychar 'xyzw' 1       ; equivalent to %define mychar 'x' 
%substr mychar 'xyzw' 2       ; equivalent to %define mychar 'y' 
%substr mychar 'xyzw' 3       ; equivalent to %define mychar 'z' 
%substr mychar 'xyzw' 2,2     ; equivalent to %define mychar 'yz' 
%substr mychar 'xyzw' 2,-1    ; equivalent to %define mychar 'yzw' 
%substr mychar 'xyzw' 2,-2    ; equivalent to %define mychar 'yz'

As with %strlen (see section 4.2.1), the first parameter is the single-line macro to be created and the second is the string. The third parameter specifies the first character to be selected, and the optional fourth parameter preceeded by comma) is the length. Note that the first index is 1, not 0 and the last index is equal to the value that %strlen would assign given the same string. Index values out of range result in an empty string. A negative length means "until N-1 characters before the end of string", i.e. -1 means until end of string, -2 until one character before, etc.

4.3 Multi-Line Macros: %macro

Multi-line macros are much more like the type of macro seen in MASM and TASM: a multi-line macro definition in NASM looks something like this.

%macro  prologue 1 

        push    ebp 
        mov     ebp,esp 
        sub     esp,%1 

%endmacro

This defines a C-like function prologue as a macro: so you @, then it does nothing to the local label mechanism. So you could code

label1:                         ; a non-local label 
.local:                         ; this is really label1.local 
..@foo:                         ; this is a special symbol 
label2:                         ; another non-local label 
.local:                         ; this is really label2.local 

        jmp     ..@foo          ; this will jump three lines up

NASM has the capacity to define other special symbols beginning with a double period: for example, ..start is used to specify the entry point in the obj output format (see section 6.2.6).

Next Chapter | Previous Chapter | Contents | Index ./usr/share/doc/nasm/html/nasmdoc4.html0000644000000000000000000023650211026070423016674 0ustar rootrootNASM Manual

The Netwide Assembler: NASM

Next Chapter | Previous Chapter | Contents | Index

Chapter 4: The NASM Preprocessor

NASM contains a powerful macro processor, which supports conditional assembly, multi-level file inclusion, two forms of macro (single-line and multi-line), and a `context stack' mechanism for extra macro power. Preprocessor directives all begin with a % sign.

The preprocessor collapses all lines which end with a backslash (\) character into a single line. Thus:

%define THIS_VERY_LONG_MACRO_NAME_IS_DEFINED_TO \ 
        THIS_VALUE

will work like a single-line macro without the backslash-newline sequence.

4.1 Single-Line Macros

4.1.1 The Normal Way: %define

Single-line macros are defined using the %define preprocessor directive. The definitions work in a similar way to C; so you can do things like

%define ctrl    0x1F & 
%define param(a,b) ((a)+(a)*(b)) 

        mov     byte [param(2,ebx)], ctrl 'D'

which will expand to

        mov     byte [(2)+(2)*(ebx)], 0x1F & 'D'

When the expansion of a single-line macro contains tokens which invoke another macro, the expansion is performed at invocation time, not at definition time. Thus the code

%define a(x)    1+b(x) 
%define b(x)    2*x 

        mov     ax,a(8)

will evaluate in the expected way to mov ax,1+2*8, even though the macro b wasn't defined at the time of definition of a.

Macros defined with %define are case sensitive: after %define foo bar, only foo will expand to bar: Foo or FOO will not. By using %idefine instead of %define (the `i' stands for `insensitive') you can define all the case variants of a macro at once, so that %idefine foo bar would cause foo, Foo, FOO, fOO and so on all to expand to bar.

There is a mechanism which detects when a macro call has occurred as a result of a previous expansion of the same macro, to guard against circular references and infinite loops. If this happens, the preprocessor will only expand the first occurrence of the macro. Hence, if you code

%define a(x)    1+a(x) 

        mov     ax,a(3)

the macro a(3) will expand once, becoming 1+a(3), and will then expand no further. This behaviour can be useful: see section 8.1 for an example of its use.

You can overload single-line macros: if you write

%define foo(x)   1+x 
%define foo(x,y) 1+x*y

the preprocessor will be able to handle both types of macro call, by counting the parameters you pass; so foo(3) will become 1+3 whereas foo(ebx,2) will become 1+ebx*2. However, if you define

%define foo bar

then no other definition of foo will be accepted: a macro with no parameters prohibits the definition of the same name as a macro with parameters, and vice versa.

This doesn't prevent single-line macros being redefined: you can perfectly well define a macro with

%define foo bar

and then re-define it later in the same source file with

%define foo baz

Then everywhere the macro foo is invoked, it will be expanded according to the most recent definition. This is particularly useful when defining single-line macros with %assign (see section 4.1.6).

You can pre-define single-line macros using the `-d' option on the NASM command line: see section 2.1.18.

4.1.2 Enhancing %define: %xdefine

To have a reference to an embedded single-line macro resolved at the time that it is embedded, as opposed to when the calling macro is expanded, you need a different mechanism to the one offered by %define. The solution is to use %xdefine, or it's case-insensitive counterpart %ixdefine.

Suppose you have the following code:

%define  isTrue  1 
%define  isFalse isTrue 
%define  isTrue  0 

val1:    db      isFalse 

%define  isTrue  1 

val2:    db      isFalse

In this case, val1 is equal to 0, and val2 is equal to 1. This is because, when a single-line macro is defined using %define, it is expanded only when it is called. As isFalse expands to isTrue, the expansion will be the current value of isTrue. The first time it is called that is 0, and the second time it is 1.

If you wanted isFalse to expand to the value assigned to the embedded macro isTrue at the time that isFalse was defined, you need to change the above code to use %xdefine.

%xdefine isTrue  1 
%xdefine isFalse isTrue 
%xdefine isTrue  0 

val1:    db      isFalse 

%xdefine isTrue  1 

val2:    db      isFalse

Now, each time that isFalse is called, it expands to 1, as that is what the embedded macro isTrue expanded to at the time that isFalse was defined.

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

As an example, consider the following:

%define BDASTART 400h                ; Start of BIOS data area

struc   tBIOSDA                      ; its structure 
        .COM1addr       RESW    1 
        .COM2addr       RESW    1 
        ; ..and so on 
endstruc

Now, if we need to access the elements of tBIOSDA in different places, we can end up with:

        mov     ax,BDASTART + tBIOSDA.COM1addr 
        mov     bx,BDASTART + tBIOSDA.COM2addr

This will become pretty ugly (and tedious) if used in many places, and can be reduced in size significantly by using the following macro:

; Macro to access BIOS variables by their names (from tBDA):

%define BDA(x)  BDASTART + tBIOSDA. %+ x

Now the above code can be written as:

        mov     ax,BDA(COM1addr) 
        mov     bx,BDA(COM2addr)

Using this feature, we can simplify references to a lot of macros (and, in turn, reduce typing errors).

4.1.4 The Macro Name Itself: %? and %??

The special symbols %? and %?? can be used to reference the macro name itself inside a macro expansion, this is supported for both single-and multi-line macros. %? refers to the macro name as invoked, whereas %?? refers to the macro name as declared. The two are always the same for case-sensitive macros, but for case-insensitive macros, they can differ.

For example:

%idefine Foo mov %?,%?? 

        foo 
        FOO

will expand to:

        mov foo,Foo 
        mov FOO,Foo

The sequence:

%idefine keyword $%?

can be used to make a keyword "disappear", for example in case a new instruction has been used as a label in older code. For example:

%idefine pause $%?                  ; Hide the PAUSE instruction

4.1.5 Undefining Macros: %undef

Single-line macros can be removed with the %undef command. For example, the following sequence:

%define foo bar 
%undef  foo 

        mov     eax, foo

will expand to the instruction mov eax, foo, since after %undef the macro foo is no longer defined.

Macros that would otherwise be pre-defined can be undefined on the command-line using the `-u' option on the NASM command line: see section 2.1.19.

4.1.6 Preprocessor Variables: %assign

An alternative way to define single-line macros is by means of the %assign command (and its case-insensitive counterpart %iassign, which differs from %assign in exactly the same way that %idefine differs from %define).

%assign is used to define single-line macros which take no parameters and have a numeric value. This value can be specified in the form of an expression, and it will be evaluated once, when the %assign directive is processed.

Like %define, macros defined using %assign can be re-defined later, so you can do things like

%assign i i+1

to increment the numeric value of a macro.

%assign is useful for controlling the termination of %rep preprocessor loops: see section 4.5 for an example of this. Another use for %assign is given in section 7.4 and section 8.1.

The expression passed to %assign is a critical expression (see section 3.8), and must also evaluate to a pure number (rather than a relocatable reference such as a code or data address, or anything involving a register).

4.1.7 Defining Strings: %defstr

%defstr, and its case-insensitive counterpart %idefstr, define or redefine a single-line macro without parameters but converts the entire right-hand side, after macro expansion, to a quoted string before definition.

For example:

%defstr test TEST

is equivalent to

%define test 'TEST'

This can be used, for example, with the %! construct (see section 4.10.2):

%defstr PATH %!PATH		; The operating system PATH variable

4.2 String Handling in Macros: %strlen and %substr

It's often useful to be able to handle strings in macros. NASM supports two simple string handling macro operators from which more complex operations can be constructed.

4.2.1 String Length: %strlen

The %strlen macro is like %assign macro in that it creates (or redefines) a numeric value to a macro. The difference is that with %strlen, the numeric value is the length of a string. An example of the use of this would be:

%strlen charcnt 'my string'

In this example, charcnt would receive the value 9, just as if an %assign had been used. In this example, 'my string' was a literal string but it could also have been a single-line macro that expands to a string, as in the following example:

%define sometext 'my string' 
%strlen charcnt sometext

As in the first case, this would result in charcnt being assigned the value of 9.

4.2.2 Sub-strings: %substr

Individual letters in strings can be extracted using %substr. An example of its use is probably more useful than the description:

%substr mychar 'xyzw' 1       ; equivalent to %define mychar 'x' 
%substr mychar 'xyzw' 2       ; equivalent to %define mychar 'y' 
%substr mychar 'xyzw' 3       ; equivalent to %define mychar 'z' 
%substr mychar 'xyzw' 2,2     ; equivalent to %define mychar 'yz' 
%substr mychar 'xyzw' 2,-1    ; equivalent to %define mychar 'yzw' 
%substr mychar 'xyzw' 2,-2    ; equivalent to %define mychar 'yz'

As with %strlen (see section 4.2.1), the first parameter is the single-line macro to be created and the second is the string. The third parameter specifies the first character to be selected, and the optional fourth parameter preceeded by comma) is the length. Note that the first index is 1, not 0 and the last index is equal to the value that %strlen would assign given the same string. Index values out of range result in an empty string. A negative length means "until N-1 characters before the end of string", i.e. -1 means until end of string, -2 until one character before, etc.

4.3 Multi-Line Macros: %macro

Multi-line macros are much more like the type of macro seen in MASM and TASM: a multi-line macro definition in NASM looks something like this.

%macro  prologue 1 

        push    ebp 
        mov     ebp,esp 
        sub     esp,%1 

%endmacro

This defines a C-like function prologue as a macro: so you @, then it does nothing to the local label mechanism. So you could code

label1:                         ; a non-local label 
.local:                         ; this is really label1.local 
..@foo:                         ; this is a special symbol 
label2:                         ; another non-local label 
.local:                         ; this is really label2.local 

        jmp     ..@foo          ; this will jump three lines up

NASM has the capacity to define other special symbols beginning with a double period: for example, ..start is used to specify the entry point in the obj output format (see section 6.2.6).