⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nasmdoc4.htm

📁 nasm手册 大家可以看看 对要写汇编程序的帮助很大
💻 HTM
📖 第 1 页 / 共 5 页
字号:
<p><pre>myfunc: push    ebp         mov     ebp,esp         sub     esp,12</pre><p>The number <code><nobr>1</nobr></code> after the macro name in the<code><nobr>%macro</nobr></code> line defines the number of parameters themacro <code><nobr>prologue</nobr></code> expects to receive. The use of<code><nobr>%1</nobr></code> inside the macro definition refers to thefirst parameter to the macro call. With a macro taking more than oneparameter, subsequent parameters would be referred to as<code><nobr>%2</nobr></code>, <code><nobr>%3</nobr></code> and so on.<p>Multi-line macros, like single-line macros, are case-sensitive, unlessyou define them using the alternative directive<code><nobr>%imacro</nobr></code>.<p>If you need to pass a comma as <em>part</em> of a parameter to amulti-line macro, you can do that by enclosing the entire parameter inbraces. So you could code things like<p><pre>%macro  silly 2     %2: db      %1 %endmacro         silly 'a', letter_a             ; letter_a:  db 'a'         silly 'ab', string_ab           ; string_ab: db 'ab'         silly {13,10}, crlf             ; crlf:      db 13,10</pre><h4><a name="section-4.3.1">4.3.1 Overloading Multi-Line Macros</a></h4><p>As with single-line macros, multi-line macros can be overloaded bydefining the same macro name several times with different numbers ofparameters. This time, no exception is made for macros with no parametersat all. So you could define<p><pre>%macro  prologue 0         push    ebp         mov     ebp,esp %endmacro</pre><p>to define an alternative form of the function prologue which allocatesno local stack space.<p>Sometimes, however, you might want to `overload' a machine instruction;for example, you might want to define<p><pre>%macro  push 2         push    %1         push    %2 %endmacro</pre><p>so that you could code<p><pre>        push    ebx             ; this line is not a macro call         push    eax,ecx         ; but this one is</pre><p>Ordinarily, NASM will give a warning for the first of the above twolines, since <code><nobr>push</nobr></code> is now defined to be a macro,and is being invoked with a number of parameters for which no definitionhas been given. The correct code will still be generated, but the assemblerwill give a warning. This warning can be disabled by the use of the<code><nobr>-w-macro-params</nobr></code> command-line option (see<a href="nasmdoc2.html#section-2.1.18">section 2.1.18</a>).<h4><a name="section-4.3.2">4.3.2 Macro-Local Labels</a></h4><p>NASM allows you to define labels within a multi-line macro definition insuch a way as to make them local to the macro call: so calling the samemacro multiple times will use a different label each time. You do this byprefixing <code><nobr>%%</nobr></code> to the label name. So you can inventan instruction which executes a <code><nobr>RET</nobr></code> if the<code><nobr>Z</nobr></code> flag is set by doing this:<p><pre>%macro  retz 0         jnz     %%skip         ret     %%skip: %endmacro</pre><p>You can call this macro as many times as you want, and every time youcall it NASM will make up a different `real' name to substitute for thelabel <code><nobr>%%skip</nobr></code>. The names NASM invents are of theform <code><nobr>..@2345.skip</nobr></code>, where the number 2345 changeswith every macro call. The <code><nobr>..@</nobr></code> prefix preventsmacro-local labels from interfering with the local label mechanism, asdescribed in <a href="nasmdoc3.html#section-3.9">section 3.9</a>. Youshould avoid defining your own labels in this form (the<code><nobr>..@</nobr></code> prefix, then a number, then another period)in case they interfere with macro-local labels.<h4><a name="section-4.3.3">4.3.3 Greedy Macro Parameters</a></h4><p>Occasionally it is useful to define a macro which lumps its entirecommand line into one parameter definition, possibly after extracting oneor two smaller parameters from the front. An example might be a macro towrite a text string to a file in MS-DOS, where you might want to be able towrite<p><pre>        writefile [filehandle],"hello, world",13,10</pre><p>NASM allows you to define the last parameter of a macro to be<em>greedy</em>, meaning that if you invoke the macro with more parametersthan it expects, all the spare parameters get lumped into the last definedone along with the separating commas. So if you code:<p><pre>%macro  writefile 2+         jmp     %%endstr   %%str:        db      %2   %%endstr:         mov     dx,%%str         mov     cx,%%endstr-%%str         mov     bx,%1         mov     ah,0x40         int     0x21 %endmacro</pre><p>then the example call to <code><nobr>writefile</nobr></code> above willwork as expected: the text before the first comma,<code><nobr>[filehandle]</nobr></code>, is used as the first macroparameter and expanded when <code><nobr>%1</nobr></code> is referred to,and all the subsequent text is lumped into <code><nobr>%2</nobr></code> andplaced after the <code><nobr>db</nobr></code>.<p>The greedy nature of the macro is indicated to NASM by the use of the<code><nobr>+</nobr></code> sign after the parameter count on the<code><nobr>%macro</nobr></code> line.<p>If you define a greedy macro, you are effectively telling NASM how itshould expand the macro given <em>any</em> number of parameters from theactual number specified up to infinity; in this case, for example, NASM nowknows what to do when it sees a call to <code><nobr>writefile</nobr></code>with 2, 3, 4 or more parameters. NASM will take this into account whenoverloading macros, and will not allow you to define another form of<code><nobr>writefile</nobr></code> taking 4 parameters (for example).<p>Of course, the above macro could have been implemented as a non-greedymacro, in which case the call to it would have had to look like<p><pre>          writefile [filehandle], {"hello, world",13,10}</pre><p>NASM provides both mechanisms for putting commas in macro parameters,and you choose which one you prefer for each macro definition.<p>See <a href="nasmdoc5.html#section-5.2.1">section 5.2.1</a> for a betterway to write the above macro.<h4><a name="section-4.3.4">4.3.4 Default Macro Parameters</a></h4><p>NASM also allows you to define a multi-line macro with a <em>range</em>of allowable parameter counts. If you do this, you can specify defaults foromitted parameters. So, for example:<p><pre>%macro  die 0-1 "Painful program death has occurred."         writefile 2,%1         mov     ax,0x4c01         int     0x21 %endmacro</pre><p>This macro (which makes use of the <code><nobr>writefile</nobr></code>macro defined in <a href="#section-4.3.3">section 4.3.3</a>) can be calledwith an explicit error message, which it will display on the error outputstream before exiting, or it can be called with no parameters, in whichcase it will use the default error message supplied in the macrodefinition.<p>In general, you supply a minimum and maximum number of parameters for amacro of this type; the minimum number of parameters are then required inthe macro call, and then you provide defaults for the optional ones. So ifa macro definition began with the line<p><pre>%macro foobar 1-3 eax,[ebx+2]</pre><p>then it could be called with between one and three parameters, and<code><nobr>%1</nobr></code> would always be taken from the macro call.<code><nobr>%2</nobr></code>, if not specified by the macro call, woulddefault to <code><nobr>eax</nobr></code>, and <code><nobr>%3</nobr></code>if not specified would default to <code><nobr>[ebx+2]</nobr></code>.<p>You may omit parameter defaults from the macro definition, in which casethe parameter default is taken to be blank. This can be useful for macroswhich can take a variable number of parameters, since the<code><nobr>%0</nobr></code> token (see <a href="#section-4.3.5">section4.3.5</a>) allows you to determine how many parameters were really passedto the macro call.<p>This defaulting mechanism can be combined with the greedy-parametermechanism; so the <code><nobr>die</nobr></code> macro above could be mademore powerful, and more useful, by changing the first line of thedefinition to<p><pre>%macro die 0-1+ "Painful program death has occurred.",13,10</pre><p>The maximum parameter count can be infinite, denoted by<code><nobr>*</nobr></code>. In this case, of course, it is impossible toprovide a <em>full</em> set of default parameters. Examples of this usageare shown in <a href="#section-4.3.6">section 4.3.6</a>.<h4><a name="section-4.3.5">4.3.5 <code><nobr>%0</nobr></code>: Macro Parameter Counter</a></h4><p>For a macro which can take a variable number of parameters, theparameter reference <code><nobr>%0</nobr></code> will return a numericconstant giving the number of parameters passed to the macro. This can beused as an argument to <code><nobr>%rep</nobr></code> (see<a href="#section-4.5">section 4.5</a>) in order to iterate through all theparameters of a macro. Examples are given in<a href="#section-4.3.6">section 4.3.6</a>.<h4><a name="section-4.3.6">4.3.6 <code><nobr>%rotate</nobr></code>: Rotating Macro Parameters</a></h4><p>Unix shell programmers will be familiar with the<code><nobr>shift</nobr></code> shell command, which allows the argumentspassed to a shell script (referenced as <code><nobr>$1</nobr></code>,<code><nobr>$2</nobr></code> and so on) to be moved left by one place, sothat the argument previously referenced as <code><nobr>$2</nobr></code>becomes available as <code><nobr>$1</nobr></code>, and the argumentpreviously referenced as <code><nobr>$1</nobr></code> is no longeravailable at all.<p>NASM provides a similar mechanism, in the form of<code><nobr>%rotate</nobr></code>. As its name suggests, it differs fromthe Unix <code><nobr>shift</nobr></code> in that no parameters are lost:parameters rotated off the left end of the argument list reappear on theright, and vice versa.<p><code><nobr>%rotate</nobr></code> is invoked with a single numericargument (which may be an expression). The macro parameters are rotated tothe left by that many places. If the argument to<code><nobr>%rotate</nobr></code> is negative, the macro parameters arerotated to the right.<p>So a pair of macros to save and restore a set of registers might work asfollows:<p><pre>%macro  multipush 1-*   %rep  %0         push    %1   %rotate 1   %endrep %endmacro</pre><p>This macro invokes the <code><nobr>PUSH</nobr></code> instruction oneach of its arguments in turn, from left to right. It begins by pushing itsfirst argument, <code><nobr>%1</nobr></code>, then invokes<code><nobr>%rotate</nobr></code> to move all the arguments one place tothe left, so that the original second argument is now available as<code><nobr>%1</nobr></code>. Repeating this procedure as many times asthere were arguments (achieved by supplying <code><nobr>%0</nobr></code> asthe argument to <code><nobr>%rep</nobr></code>) causes each argument inturn to be pushed.<p>Note also the use of <code><nobr>*</nobr></code> as the maximumparameter count, indicating that there is no upper limit on the number ofparameters you may supply to the <code><nobr>multipush</nobr></code> macro.<p>It would be convenient, when using this macro, to have a<code><nobr>POP</nobr></code> equivalent, which <em>didn't</em> require thearguments to be given in reverse order. Ideally, you would write the<code><nobr>multipush</nobr></code> macro call, then cut-and-paste the lineto where the pop needed to be done, and change the name of the called macroto <code><nobr>multipop</nobr></code>, and the macro would take care ofpopping the registers in the opposite order from the one in which they werepushed.<p>This can be done by the following definition:<p><pre>%macro  multipop 1-*   %rep %0   %rotate -1         pop     %1   %endrep %endmacro</pre><p>This macro begins by rotating its arguments one place to the<em>right</em>, so that the original <em>last</em> argument appears as<code><nobr>%1</nobr></code>. This is then popped, and the arguments arerotated right again, so the second-to-last argument becomes<code><nobr>%1</nobr></code>. Thus the arguments are iterated through inreverse order.<h4><a name="section-4.3.7">4.3.7 Concatenating Macro Parameters</a></h4><p>NASM can concatenate macro parameters on to other text surrounding them.This allows you to declare a family of symbols, for example, in a macrodefinition. If, for example, you wanted to generate a table of key codesalong with offsets into the table, you could code something like<p><pre>%macro keytab_entry 2     keypos%1    equ     $-keytab                 db      %2 %endmacro keytab:           keytab_entry F1,128+1           keytab_entry F2,128+2           keytab_entry Return,13</pre><p>which would expand to<p><pre>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -