📄 nasmdoc4.htm
字号:
<html><head><title>NASM Manual</title></head><body><h1 align=center>The Netwide Assembler: NASM</h1><p align=center><a href="nasmdoc5.html">Next Chapter</a> |<a href="nasmdoc3.html">Previous Chapter</a> |<a href="nasmdoc0.html">Contents</a> |<a href="nasmdoci.html">Index</a><h2><a name="chapter-4">Chapter 4: The NASM Preprocessor</a></h2><p>NASM contains a powerful macro processor, which supports conditionalassembly, multi-level file inclusion, two forms of macro (single-line andmulti-line), and a `context stack' mechanism for extra macro power.Preprocessor directives all begin with a <code><nobr>%</nobr></code> sign.<p>The preprocessor collapses all lines which end with a backslash (\)character into a single line. Thus:<p><pre>%define THIS_VERY_LONG_MACRO_NAME_IS_DEFINED_TO \ THIS_VALUE</pre><p>will work like a single-line macro without the backslash-newlinesequence.<h3><a name="section-4.1">4.1 Single-Line Macros</a></h3><h4><a name="section-4.1.1">4.1.1 The Normal Way: <code><nobr>%define</nobr></code></a></h4><p>Single-line macros are defined using the<code><nobr>%define</nobr></code> preprocessor directive. The definitionswork in a similar way to C; so you can do things like<p><pre>%define ctrl 0x1F & %define param(a,b) ((a)+(a)*(b)) mov byte [param(2,ebx)], ctrl 'D'</pre><p>which will expand to<p><pre> mov byte [(2)+(2)*(ebx)], 0x1F & 'D'</pre><p>When the expansion of a single-line macro contains tokens which invokeanother macro, the expansion is performed at invocation time, not atdefinition time. Thus the code<p><pre>%define a(x) 1+b(x) %define b(x) 2*x mov ax,a(8)</pre><p>will evaluate in the expected way to<code><nobr>mov ax,1+2*8</nobr></code>, even though the macro<code><nobr>b</nobr></code> wasn't defined at the time of definition of<code><nobr>a</nobr></code>.<p>Macros defined with <code><nobr>%define</nobr></code> are casesensitive: after <code><nobr>%define foo bar</nobr></code>, only<code><nobr>foo</nobr></code> will expand to <code><nobr>bar</nobr></code>:<code><nobr>Foo</nobr></code> or <code><nobr>FOO</nobr></code> will not. Byusing <code><nobr>%idefine</nobr></code> instead of<code><nobr>%define</nobr></code> (the `i' stands for `insensitive') youcan define all the case variants of a macro at once, so that<code><nobr>%idefine foo bar</nobr></code> would cause<code><nobr>foo</nobr></code>, <code><nobr>Foo</nobr></code>,<code><nobr>FOO</nobr></code>, <code><nobr>fOO</nobr></code> and so on allto expand to <code><nobr>bar</nobr></code>.<p>There is a mechanism which detects when a macro call has occurred as aresult of a previous expansion of the same macro, to guard against circularreferences and infinite loops. If this happens, the preprocessor will onlyexpand the first occurrence of the macro. Hence, if you code<p><pre>%define a(x) 1+a(x) mov ax,a(3)</pre><p>the macro <code><nobr>a(3)</nobr></code> will expand once, becoming<code><nobr>1+a(3)</nobr></code>, and will then expand no further. Thisbehaviour can be useful: see <a href="nasmdoc8.html#section-8.1">section8.1</a> for an example of its use.<p>You can overload single-line macros: if you write<p><pre>%define foo(x) 1+x %define foo(x,y) 1+x*y</pre><p>the preprocessor will be able to handle both types of macro call, bycounting the parameters you pass; so <code><nobr>foo(3)</nobr></code> willbecome <code><nobr>1+3</nobr></code> whereas<code><nobr>foo(ebx,2)</nobr></code> will become<code><nobr>1+ebx*2</nobr></code>. However, if you define<p><pre>%define foo bar</pre><p>then no other definition of <code><nobr>foo</nobr></code> will beaccepted: a macro with no parameters prohibits the definition of the samename as a macro <em>with</em> parameters, and vice versa.<p>This doesn't prevent single-line macros being <em>redefined</em>: youcan perfectly well define a macro with<p><pre>%define foo bar</pre><p>and then re-define it later in the same source file with<p><pre>%define foo baz</pre><p>Then everywhere the macro <code><nobr>foo</nobr></code> is invoked, itwill be expanded according to the most recent definition. This isparticularly useful when defining single-line macros with<code><nobr>%assign</nobr></code> (see <a href="#section-4.1.5">section4.1.5</a>).<p>You can pre-define single-line macros using the `-d' option on the NASMcommand line: see <a href="nasmdoc2.html#section-2.1.12">section2.1.12</a>.<h4><a name="section-4.1.2">4.1.2 Enhancing %define: <code><nobr>%xdefine</nobr></code></a></h4><p>To have a reference to an embedded single-line macro resolved at thetime that it is embedded, as opposed to when the calling macro is expanded,you need a different mechanism to the one offered by<code><nobr>%define</nobr></code>. The solution is to use<code><nobr>%xdefine</nobr></code>, or it's case-insensitive counterpart<code><nobr>%xidefine</nobr></code>.<p>Suppose you have the following code:<p><pre>%define isTrue 1 %define isFalse isTrue %define isTrue 0 val1: db isFalse %define isTrue 1 val2: db isFalse</pre><p>In this case, <code><nobr>val1</nobr></code> is equal to 0, and<code><nobr>val2</nobr></code> is equal to 1. This is because, when asingle-line macro is defined using <code><nobr>%define</nobr></code>, it isexpanded only when it is called. As <code><nobr>isFalse</nobr></code>expands to <code><nobr>isTrue</nobr></code>, the expansion will be thecurrent value of <code><nobr>isTrue</nobr></code>. The first time it iscalled that is 0, and the second time it is 1.<p>If you wanted <code><nobr>isFalse</nobr></code> to expand to the valueassigned to the embedded macro <code><nobr>isTrue</nobr></code> at the timethat <code><nobr>isFalse</nobr></code> was defined, you need to change theabove code to use <code><nobr>%xdefine</nobr></code>.<p><pre>%xdefine isTrue 1 %xdefine isFalse isTrue %xdefine isTrue 0 val1: db isFalse %xdefine isTrue 1 val2: db isFalse</pre><p>Now, each time that <code><nobr>isFalse</nobr></code> is called, itexpands to 1, as that is what the embedded macro<code><nobr>isTrue</nobr></code> expanded to at the time that<code><nobr>isFalse</nobr></code> was defined.<h4><a name="section-4.1.3">4.1.3 Concatenating Single Line Macro Tokens: <code><nobr>%+</nobr></code></a></h4><p>Individual tokens in single line macros can be concatenated, to producelonger tokens for later processing. This can be useful if there are severalsimilar macros that perform similar functions.<p>As an example, consider the following:<p><pre>%define BDASTART 400h ; Start of BIOS data area</pre><p><pre>struc tBIOSDA ; its structure .COM1addr RESW 1 .COM2addr RESW 1 ; ..and so on endstruc</pre><p>Now, if we need to access the elements of tBIOSDA in different places,we can end up with:<p><pre> mov ax,BDASTART + tBIOSDA.COM1addr mov bx,BDASTART + tBIOSDA.COM2addr</pre><p>This will become pretty ugly (and tedious) if used in many places, andcan be reduced in size significantly by using the following macro:<p><pre>; Macro to access BIOS variables by their names (from tBDA):</pre><p><pre>%define BDA(x) BDASTART + tBIOSDA. %+ x</pre><p>Now the above code can be written as:<p><pre> mov ax,BDA(COM1addr) mov bx,BDA(COM2addr)</pre><p>Using this feature, we can simplify references to a lot of macros (and,in turn, reduce typing errors).<h4><a name="section-4.1.4">4.1.4 Undefining macros: <code><nobr>%undef</nobr></code></a></h4><p>Single-line macros can be removed with the<code><nobr>%undef</nobr></code> command. For example, the followingsequence:<p><pre>%define foo bar %undef foo mov eax, foo</pre><p>will expand to the instruction <code><nobr>mov eax, foo</nobr></code>,since after <code><nobr>%undef</nobr></code> the macro<code><nobr>foo</nobr></code> is no longer defined.<p>Macros that would otherwise be pre-defined can be undefined on thecommand-line using the `-u' option on the NASM command line: see<a href="nasmdoc2.html#section-2.1.13">section 2.1.13</a>.<h4><a name="section-4.1.5">4.1.5 Preprocessor Variables: <code><nobr>%assign</nobr></code></a></h4><p>An alternative way to define single-line macros is by means of the<code><nobr>%assign</nobr></code> command (and its case-insensitivecounterpart <code><nobr>%iassign</nobr></code>, which differs from<code><nobr>%assign</nobr></code> in exactly the same way that<code><nobr>%idefine</nobr></code> differs from<code><nobr>%define</nobr></code>).<p><code><nobr>%assign</nobr></code> is used to define single-line macroswhich take no parameters and have a numeric value. This value can bespecified in the form of an expression, and it will be evaluated once, whenthe <code><nobr>%assign</nobr></code> directive is processed.<p>Like <code><nobr>%define</nobr></code>, macros defined using<code><nobr>%assign</nobr></code> can be re-defined later, so you can dothings like<p><pre>%assign i i+1</pre><p>to increment the numeric value of a macro.<p><code><nobr>%assign</nobr></code> is useful for controlling thetermination of <code><nobr>%rep</nobr></code> preprocessor loops: see<a href="#section-4.5">section 4.5</a> for an example of this. Another usefor <code><nobr>%assign</nobr></code> is given in<a href="nasmdoc7.html#section-7.4">section 7.4</a> and<a href="nasmdoc8.html#section-8.1">section 8.1</a>.<p>The expression passed to <code><nobr>%assign</nobr></code> is a criticalexpression (see <a href="nasmdoc3.html#section-3.8">section 3.8</a>), andmust also evaluate to a pure number (rather than a relocatable referencesuch as a code or data address, or anything involving a register).<h3><a name="section-4.2">4.2 String Handling in Macros: <code><nobr>%strlen</nobr></code> and <code><nobr>%substr</nobr></code></a></h3><p>It's often useful to be able to handle strings in macros. NASM supportstwo simple string handling macro operators from which more complexoperations can be constructed.<h4><a name="section-4.2.1">4.2.1 String Length: <code><nobr>%strlen</nobr></code></a></h4><p>The <code><nobr>%strlen</nobr></code> macro is like<code><nobr>%assign</nobr></code> macro in that it creates (or redefines) anumeric value to a macro. The difference is that with<code><nobr>%strlen</nobr></code>, the numeric value is the length of astring. An example of the use of this would be:<p><pre>%strlen charcnt 'my string'</pre><p>In this example, <code><nobr>charcnt</nobr></code> would receive thevalue 8, just as if an <code><nobr>%assign</nobr></code> had been used. Inthis example, <code><nobr>'my string'</nobr></code> was a literal stringbut it could also have been a single-line macro that expands to a string,as in the following example:<p><pre>%define sometext 'my string' %strlen charcnt sometext</pre><p>As in the first case, this would result in<code><nobr>charcnt</nobr></code> being assigned the value of 8.<h4><a name="section-4.2.2">4.2.2 Sub-strings: <code><nobr>%substr</nobr></code></a></h4><p>Individual letters in strings can be extracted using<code><nobr>%substr</nobr></code>. An example of its use is probably moreuseful than the description:<p><pre>%substr mychar 'xyz' 1 ; equivalent to %define mychar 'x' %substr mychar 'xyz' 2 ; equivalent to %define mychar 'y' %substr mychar 'xyz' 3 ; equivalent to %define mychar 'z'</pre><p>In this example, mychar gets the value of 'y'. As with<code><nobr>%strlen</nobr></code> (see <a href="#section-4.2.1">section4.2.1</a>), the first parameter is the single-line macro to be created andthe second is the string. The third parameter specifies which character isto be selected. Note that the first index is 1, not 0 and the last index isequal to the value that <code><nobr>%strlen</nobr></code> would assigngiven the same string. Index values out of range result in an empty string.<h3><a name="section-4.3">4.3 Multi-Line Macros: <code><nobr>%macro</nobr></code></a></h3><p>Multi-line macros are much more like the type of macro seen in MASM andTASM: a multi-line macro definition in NASM looks something like this.<p><pre>%macro prologue 1 push ebp mov ebp,esp sub esp,%1 %endmacro</pre><p>This defines a C-like function prologue as a macro: so you would invokethe macro with a call such as<p><pre>myfunc: prologue 12</pre><p>which would expand to the three lines of code
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -