📄 nasmdoc4.htm
字号:
So, under NASM 0.98.32p1 for example,<code><nobr>__NASM_MAJOR__</nobr></code> would be defined to be 0,<code><nobr>__NASM_MINOR__</nobr></code> would be defined as 98,<code><nobr>__NASM_SUBMINOR__</nobr></code> would be defined to 32, and<code><nobr>___NASM_PATCHLEVEL__</nobr></code> would be defined as 1.<h4><a name="section-4.8.2">4.8.2 <code><nobr>__NASM_VERSION_ID__</nobr></code>: NASM Version ID</a></h4><p>The single-line macro <code><nobr>__NASM_VERSION_ID__</nobr></code>expands to a dword integer representing the full version number of theversion of nasm being used. The value is the equivalent to<code><nobr>__NASM_MAJOR__</nobr></code>,<code><nobr>__NASM_MINOR__</nobr></code>,<code><nobr>__NASM_SUBMINOR__</nobr></code> and<code><nobr>___NASM_PATCHLEVEL__</nobr></code> concatenated to produce asingle doubleword. Hence, for 0.98.32p1, the returned number would beequivalent to:<p><pre> dd 0x00622001</pre><p>or<p><pre> db 1,32,98,0</pre><p>Note that the above lines are generate exactly the same code, the secondline is used just to give an indication of the order that the separatevalues will be present in memory.<h4><a name="section-4.8.3">4.8.3 <code><nobr>__NASM_VER__</nobr></code>: NASM Version string</a></h4><p>The single-line macro <code><nobr>__NASM_VER__</nobr></code> expands toa string which defines the version number of nasm being used. So, underNASM 0.98.32 for example,<p><pre> db __NASM_VER__</pre><p>would expand to<p><pre> db "0.98.32"</pre><h4><a name="section-4.8.4">4.8.4 <code><nobr>__FILE__</nobr></code> and <code><nobr>__LINE__</nobr></code>: File Name and Line Number</a></h4><p>Like the C preprocessor, NASM allows the user to find out the file nameand line number containing the current instruction. The macro<code><nobr>__FILE__</nobr></code> expands to a string constant giving thename of the current input file (which may change through the course ofassembly if <code><nobr>%include</nobr></code> directives are used), and<code><nobr>__LINE__</nobr></code> expands to a numeric constant giving thecurrent line number in the input file.<p>These macros could be used, for example, to communicate debugginginformation to a macro, since invoking <code><nobr>__LINE__</nobr></code>inside a macro definition (either single-line or multi-line) will returnthe line number of the macro <em>call</em>, rather than<em>definition</em>. So to determine where in a piece of code a crash isoccurring, for example, one could write a routine<code><nobr>stillhere</nobr></code>, which is passed a line number in<code><nobr>EAX</nobr></code> and outputs something like `line 155: stillhere'. You could then write a macro<p><pre>%macro notdeadyet 0 push eax mov eax,__LINE__ call stillhere pop eax %endmacro</pre><p>and then pepper your code with calls to<code><nobr>notdeadyet</nobr></code> until you find the crash point.<h4><a name="section-4.8.5">4.8.5 <code><nobr>STRUC</nobr></code> and <code><nobr>ENDSTRUC</nobr></code>: Declaring Structure Data Types</a></h4><p>The core of NASM contains no intrinsic means of defining datastructures; instead, the preprocessor is sufficiently powerful that datastructures can be implemented as a set of macros. The macros<code><nobr>STRUC</nobr></code> and <code><nobr>ENDSTRUC</nobr></code> areused to define a structure data type.<p><code><nobr>STRUC</nobr></code> takes one parameter, which is the nameof the data type. This name is defined as a symbol with the value zero, andalso has the suffix <code><nobr>_size</nobr></code> appended to it and isthen defined as an <code><nobr>EQU</nobr></code> giving the size of thestructure. Once <code><nobr>STRUC</nobr></code> has been issued, you aredefining the structure, and should define fields using the<code><nobr>RESB</nobr></code> family of pseudo-instructions, and theninvoke <code><nobr>ENDSTRUC</nobr></code> to finish the definition.<p>For example, to define a structure called<code><nobr>mytype</nobr></code> containing a longword, a word, a byte anda string of bytes, you might code<p><pre>struc mytype mt_long: resd 1 mt_word: resw 1 mt_byte: resb 1 mt_str: resb 32 endstruc</pre><p>The above code defines six symbols: <code><nobr>mt_long</nobr></code> as0 (the offset from the beginning of a <code><nobr>mytype</nobr></code>structure to the longword field), <code><nobr>mt_word</nobr></code> as 4,<code><nobr>mt_byte</nobr></code> as 6, <code><nobr>mt_str</nobr></code> as7, <code><nobr>mytype_size</nobr></code> as 39, and<code><nobr>mytype</nobr></code> itself as zero.<p>The reason why the structure type name is defined at zero is a sideeffect of allowing structures to work with the local label mechanism: ifyour structure members tend to have the same names in more than onestructure, you can define the above structure like this:<p><pre>struc mytype .long: resd 1 .word: resw 1 .byte: resb 1 .str: resb 32 endstruc</pre><p>This defines the offsets to the structure fields as<code><nobr>mytype.long</nobr></code>,<code><nobr>mytype.word</nobr></code>,<code><nobr>mytype.byte</nobr></code> and<code><nobr>mytype.str</nobr></code>.<p>NASM, since it has no <em>intrinsic</em> structure support, does notsupport any form of period notation to refer to the elements of a structureonce you have one (except the above local-label notation), so code such as<code><nobr>mov ax,[mystruc.mt_word]</nobr></code> is not valid.<code><nobr>mt_word</nobr></code> is a constant just like any otherconstant, so the correct syntax is<code><nobr>mov ax,[mystruc+mt_word]</nobr></code> or<code><nobr>mov ax,[mystruc+mytype.word]</nobr></code>.<h4><a name="section-4.8.6">4.8.6 <code><nobr>ISTRUC</nobr></code>, <code><nobr>AT</nobr></code> and <code><nobr>IEND</nobr></code>: Declaring Instances of Structures</a></h4><p>Having defined a structure type, the next thing you typically want to dois to declare instances of that structure in your data segment. NASMprovides an easy way to do this in the <code><nobr>ISTRUC</nobr></code>mechanism. To declare a structure of type <code><nobr>mytype</nobr></code>in a program, you code something like this:<p><pre>mystruc: istruc mytype at mt_long, dd 123456 at mt_word, dw 1024 at mt_byte, db 'x' at mt_str, db 'hello, world', 13, 10, 0 iend</pre><p>The function of the <code><nobr>AT</nobr></code> macro is to make use ofthe <code><nobr>TIMES</nobr></code> prefix to advance the assembly positionto the correct point for the specified structure field, and then to declarethe specified data. Therefore the structure fields must be declared in thesame order as they were specified in the structure definition.<p>If the data to go in a structure field requires more than one sourceline to specify, the remaining source lines can easily come after the<code><nobr>AT</nobr></code> line. For example:<p><pre> at mt_str, db 123,134,145,156,167,178,189 db 190,100,0</pre><p>Depending on personal taste, you can also omit the code part of the<code><nobr>AT</nobr></code> line completely, and start the structure fieldon the next line:<p><pre> at mt_str db 'hello, world' db 13,10,0</pre><h4><a name="section-4.8.7">4.8.7 <code><nobr>ALIGN</nobr></code> and <code><nobr>ALIGNB</nobr></code>: Data Alignment</a></h4><p>The <code><nobr>ALIGN</nobr></code> and <code><nobr>ALIGNB</nobr></code>macros provides a convenient way to align code or data on a word, longword,paragraph or other boundary. (Some assemblers call this directive<code><nobr>EVEN</nobr></code>.) The syntax of the<code><nobr>ALIGN</nobr></code> and <code><nobr>ALIGNB</nobr></code> macrosis<p><pre> align 4 ; align on 4-byte boundary align 16 ; align on 16-byte boundary align 8,db 0 ; pad with 0s rather than NOPs align 4,resb 1 ; align to 4 in the BSS alignb 4 ; equivalent to previous line</pre><p>Both macros require their first argument to be a power of two; they bothcompute the number of additional bytes required to bring the length of thecurrent section up to a multiple of that power of two, and then apply the<code><nobr>TIMES</nobr></code> prefix to their second argument to performthe alignment.<p>If the second argument is not specified, the default for<code><nobr>ALIGN</nobr></code> is <code><nobr>NOP</nobr></code>, and thedefault for <code><nobr>ALIGNB</nobr></code> is<code><nobr>RESB 1</nobr></code>. So if the second argument is specified,the two macros are equivalent. Normally, you can just use<code><nobr>ALIGN</nobr></code> in code and data sections and<code><nobr>ALIGNB</nobr></code> in BSS sections, and never need the secondargument except for special purposes.<p><code><nobr>ALIGN</nobr></code> and <code><nobr>ALIGNB</nobr></code>,being simple macros, perform no error checking: they cannot warn you iftheir first argument fails to be a power of two, or if their secondargument generates more than one byte of code. In each of these cases theywill silently do the wrong thing.<p><code><nobr>ALIGNB</nobr></code> (or <code><nobr>ALIGN</nobr></code>with a second argument of <code><nobr>RESB 1</nobr></code>) can be usedwithin structure definitions:<p><pre>struc mytype2 mt_byte: resb 1 alignb 2 mt_word: resw 1 alignb 4 mt_long: resd 1 mt_str: resb 32 endstruc</pre><p>This will ensure that the structure members are sensibly alignedrelative to the base of the structure.<p>A final caveat: <code><nobr>ALIGN</nobr></code> and<code><nobr>ALIGNB</nobr></code> work relative to the beginning of the<em>section</em>, not the beginning of the address space in the finalexecutable. Aligning to a 16-byte boundary when the section you're in isonly guaranteed to be aligned to a 4-byte boundary, for example, is a wasteof effort. Again, NASM does not check that the section's alignmentcharacteristics are sensible for the use of <code><nobr>ALIGN</nobr></code>or <code><nobr>ALIGNB</nobr></code>.<h3><a name="section-4.9">4.9 TASM Compatible Preprocessor Directives</a></h3><p>The following preprocessor directives may only be used when TASMcompatibility is turned on using the <code><nobr>-t</nobr></code> commandline switch (This switch is described in<a href="nasmdoc2.html#section-2.1.17">section 2.1.17</a>.)<ul><li><code><nobr>%arg</nobr></code> (see <a href="#section-4.9.1">section4.9.1</a>)<li><code><nobr>%stacksize</nobr></code> (see<a href="#section-4.9.2">section 4.9.2</a>)<li><code><nobr>%local</nobr></code> (see <a href="#section-4.9.3">section4.9.3</a>)</ul><h4><a name="section-4.9.1">4.9.1 <code><nobr>%arg</nobr></code> Directive</a></h4><p>The <code><nobr>%arg</nobr></code> directive is used to simplify thehandling of parameters passed on the stack. Stack based parameter passingis used by many high level languages, including C, C++ and Pascal.<p>While NASM comes with macros which attempt to duplicate thisfunctionality (see <a href="nasmdoc7.html#section-7.4.5">section7.4.5</a>), the syntax is not particularly convenient to use and is notTASM compatible. Here is an example which shows the use of<code><nobr>%arg</nobr></code> without any external macros:<p><pre>some_function: %push mycontext ; save the current context %stacksize large ; tell NASM to use bp %arg i:word, j_ptr:word mov ax,[i] mov bx,[j_ptr] add ax,[bx] ret %pop ; restore original context</pre><p>This is similar to the procedure defined in<a href="nasmdoc7.html#section-7.4.5">section 7.4.5</a> and adds the valuein i to the value pointed to by j_ptr and returns the sum in the axregister. See <a href="#section-4.7.1">section 4.7.1</a> for an explanationof <code><nobr>push</nobr></code> and <code><nobr>pop</nobr></code> and theuse of context stacks.<h4><a name="section-4.9.2">4.9.2 <code><nobr>%stacksize</nobr></code> Directive</a></h4><p>The <code><nobr>%stacksize</nobr></code> directive is used inconjunction with the <code><nobr>%arg</nobr></code> (see<a href="#section-4.9.1">section 4.9.1</a>) and the<code><nobr>%local</nobr></code> (see <a href="#section-4.9.3">section4.9.3</a>) directives. It tells NASM the default size to use for subsequent<code><nobr>%arg</nobr></code> and <code><nobr>%local</nobr></code>directives. The <code><nobr>%stacksize</nobr></code> directive takes onerequired argument which is one of <code><nobr>flat</nobr></code>,<code><nobr>large</nobr></code> or <code><nobr>small</nobr></code>.<p><pre>%stacksize flat</pre><p>This form causes NASM to use stack-based parameter addressing relativeto <code><nobr>ebp</nobr></code> and it assumes that a near form of callwas used to get to this label (i.e. that <code><nobr>eip</nobr></code> ison the stack).<p><pre>%stacksize large</pre><p>This form uses <code><nobr>bp</nobr></code> to do stack-based parameteraddressing and
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -