📄 nasmdoc3.htm
字号:
<code><nobr>64-$+buffer</nobr></code> as above. To repeat more than oneline of code, or a complex macro, use the preprocessor<code><nobr>%rep</nobr></code> directive.<h3><a name="section-3.3">3.3 Effective Addresses</a></h3><p>An effective address is any operand to an instruction which referencesmemory. Effective addresses, in NASM, have a very simple syntax: theyconsist of an expression evaluating to the desired address, enclosed insquare brackets. For example:<p><pre>wordvar dw 123 mov ax,[wordvar] mov ax,[wordvar+1] mov ax,[es:wordvar+bx]</pre><p>Anything not conforming to this simple system is not a valid memoryreference in NASM, for example <code><nobr>es:wordvar[bx]</nobr></code>.<p>More complicated effective addresses, such as those involving more thanone register, work in exactly the same way:<p><pre> mov eax,[ebx*2+ecx+offset] mov ax,[bp+di+8]</pre><p>NASM is capable of doing algebra on these effective addresses, so thatthings which don't necessarily <em>look</em> legal are perfectly all right:<p><pre> mov eax,[ebx*5] ; assembles as [ebx*4+ebx] mov eax,[label1*2-label2] ; ie [label1+(label1-label2)]</pre><p>Some forms of effective address have more than one assembled form; inmost such cases NASM will generate the smallest form it can. For example,there are distinct assembled forms for the 32-bit effective addresses<code><nobr>[eax*2+0]</nobr></code> and<code><nobr>[eax+eax]</nobr></code>, and NASM will generally generate thelatter on the grounds that the former requires four bytes to store a zerooffset.<p>NASM has a hinting mechanism which will cause<code><nobr>[eax+ebx]</nobr></code> and <code><nobr>[ebx+eax]</nobr></code>to generate different opcodes; this is occasionally useful because<code><nobr>[esi+ebp]</nobr></code> and <code><nobr>[ebp+esi]</nobr></code>have different default segment registers.<p>However, you can force NASM to generate an effective address in aparticular form by the use of the keywords <code><nobr>BYTE</nobr></code>,<code><nobr>WORD</nobr></code>, <code><nobr>DWORD</nobr></code> and<code><nobr>NOSPLIT</nobr></code>. If you need<code><nobr>[eax+3]</nobr></code> to be assembled using a double-wordoffset field instead of the one byte NASM will normally generate, you cancode <code><nobr>[dword eax+3]</nobr></code>. Similarly, you can force NASMto use a byte offset for a small value which it hasn't seen on the firstpass (see <a href="#section-3.8">section 3.8</a> for an example of such acode fragment) by using <code><nobr>[byte eax+offset]</nobr></code>. Asspecial cases, <code><nobr>[byte eax]</nobr></code> will code<code><nobr>[eax+0]</nobr></code> with a byte offset of zero, and<code><nobr>[dword eax]</nobr></code> will code it with a double-wordoffset of zero. The normal form, <code><nobr>[eax]</nobr></code>, will becoded with no offset field.<p>The form described in the previous paragraph is also useful if you aretrying to access data in a 32-bit segment from within 16 bit code. For moreinformation on this see the section on mixed-size addressing(<a href="nasmdoc9.html#section-9.2">section 9.2</a>). In particular, ifyou need to access data with a known offset that is larger than will fit ina 16-bit value, if you don't specify that it is a dword offset, nasm willcause the high word of the offset to be lost.<p>Similarly, NASM will split <code><nobr>[eax*2]</nobr></code> into<code><nobr>[eax+eax]</nobr></code> because that allows the offset field tobe absent and space to be saved; in fact, it will also split<code><nobr>[eax*2+offset]</nobr></code> into<code><nobr>[eax+eax+offset]</nobr></code>. You can combat this behaviourby the use of the <code><nobr>NOSPLIT</nobr></code> keyword:<code><nobr>[nosplit eax*2]</nobr></code> will force<code><nobr>[eax*2+0]</nobr></code> to be generated literally.<h3><a name="section-3.4">3.4 Constants</a></h3><p>NASM understands four different types of constant: numeric, character,string and floating-point.<h4><a name="section-3.4.1">3.4.1 Numeric Constants</a></h4><p>A numeric constant is simply a number. NASM allows you to specifynumbers in a variety of number bases, in a variety of ways: you can suffix<code><nobr>H</nobr></code>, <code><nobr>Q</nobr></code> or<code><nobr>O</nobr></code>, and <code><nobr>B</nobr></code> for hex, octaland binary, or you can prefix <code><nobr>0x</nobr></code> for hex in thestyle of C, or you can prefix <code><nobr>$</nobr></code> for hex in thestyle of Borland Pascal. Note, though, that the <code><nobr>$</nobr></code>prefix does double duty as a prefix on identifiers (see<a href="#section-3.1">section 3.1</a>), so a hex number prefixed with a<code><nobr>$</nobr></code> sign must have a digit after the<code><nobr>$</nobr></code> rather than a letter.<p>Some examples:<p><pre> mov ax,100 ; decimal mov ax,0a2h ; hex mov ax,$0a2 ; hex again: the 0 is required mov ax,0xa2 ; hex yet again mov ax,777q ; octal mov ax,777o ; octal again mov ax,10010011b ; binary</pre><h4><a name="section-3.4.2">3.4.2 Character Constants</a></h4><p>A character constant consists of up to four characters enclosed ineither single or double quotes. The type of quote makes no difference toNASM, except of course that surrounding the constant with single quotesallows double quotes to appear within it and vice versa.<p>A character constant with more than one character will be arranged withlittle-endian order in mind: if you code<p><pre> mov eax,'abcd'</pre><p>then the constant generated is not <code><nobr>0x61626364</nobr></code>,but <code><nobr>0x64636261</nobr></code>, so that if you were then to storethe value into memory, it would read <code><nobr>abcd</nobr></code> ratherthan <code><nobr>dcba</nobr></code>. This is also the sense of characterconstants understood by the Pentium's <code><nobr>CPUID</nobr></code>instruction (see <a href="nasmdocb.html#section-B.4.34">sectionB.4.34</a>).<h4><a name="section-3.4.3">3.4.3 String Constants</a></h4><p>String constants are only acceptable to some pseudo-instructions, namelythe <code><nobr>DB</nobr></code> family and<code><nobr>INCBIN</nobr></code>.<p>A string constant looks like a character constant, only longer. It istreated as a concatenation of maximum-size character constants for theconditions. So the following are equivalent:<p><pre> db 'hello' ; string constant db 'h','e','l','l','o' ; equivalent character constants</pre><p>And the following are also equivalent:<p><pre> dd 'ninechars' ; doubleword string constant dd 'nine','char','s' ; becomes three doublewords db 'ninechars',0,0,0 ; and really looks like this</pre><p>Note that when used as an operand to <code><nobr>db</nobr></code>, aconstant like <code><nobr>'ab'</nobr></code> is treated as a stringconstant despite being short enough to be a character constant, becauseotherwise <code><nobr>db 'ab'</nobr></code> would have the same effect as<code><nobr>db 'a'</nobr></code>, which would be silly. Similarly,three-character or four-character constants are treated as strings whenthey are operands to <code><nobr>dw</nobr></code>.<h4><a name="section-3.4.4">3.4.4 Floating-Point Constants</a></h4><p>Floating-point constants are acceptable only as arguments to<code><nobr>DD</nobr></code>, <code><nobr>DQ</nobr></code> and<code><nobr>DT</nobr></code>. They are expressed in the traditional form:digits, then a period, then optionally more digits, then optionally an<code><nobr>E</nobr></code> followed by an exponent. The period ismandatory, so that NASM can distinguish between<code><nobr>dd 1</nobr></code>, which declares an integer constant, and<code><nobr>dd 1.0</nobr></code> which declares a floating-point constant.<p>Some examples:<p><pre> dd 1.2 ; an easy one dq 1.e10 ; 10,000,000,000 dq 1.e+10 ; synonymous with 1.e10 dq 1.e-10 ; 0.000 000 000 1 dt 3.141592653589793238462 ; pi</pre><p>NASM cannot do compile-time arithmetic on floating-point constants. Thisis because NASM is designed to be portable - although it always generatescode to run on x86 processors, the assembler itself can run on any systemwith an ANSI C compiler. Therefore, the assembler cannot guarantee thepresence of a floating-point unit capable of handling the Intel numberformats, and so for NASM to be able to do floating arithmetic it would haveto include its own complete set of floating-point routines, which wouldsignificantly increase the size of the assembler for very little benefit.<h3><a name="section-3.5">3.5 Expressions</a></h3><p>Expressions in NASM are similar in syntax to those in C.<p>NASM does not guarantee the size of the integers used to evaluateexpressions at compile time: since NASM can compile and run on 64-bitsystems quite happily, don't assume that expressions are evaluated in32-bit registers and so try to make deliberate use of integer overflow. Itmight not always work. The only thing NASM will guarantee is what'sguaranteed by ANSI C: you always have <em>at least</em> 32 bits to work in.<p>NASM supports two special tokens in expressions, allowing calculationsto involve the current assembly position: the <code><nobr>$</nobr></code>and <code><nobr>$$</nobr></code> tokens. <code><nobr>$</nobr></code>evaluates to the assembly position at the beginning of the line containingthe expression; so you can code an infinite loop using<code><nobr>JMP $</nobr></code>. <code><nobr>$$</nobr></code> evaluates tothe beginning of the current section; so you can tell how far into thesection you are by using <code><nobr>($-$$)</nobr></code>.<p>The arithmetic operators provided by NASM are listed here, in increasingorder of precedence.<h4><a name="section-3.5.1">3.5.1 <code><nobr>|</nobr></code>: Bitwise OR Operator</a></h4><p>The <code><nobr>|</nobr></code> operator gives a bitwise OR, exactly asperformed by the <code><nobr>OR</nobr></code> machine instruction. BitwiseOR is the lowest-priority arithmetic operator supported by NASM.<h4><a name="section-3.5.2">3.5.2 <code><nobr>^</nobr></code>: Bitwise XOR Operator</a></h4><p><code><nobr>^</nobr></code> provides the bitwise XOR operation.<h4><a name="section-3.5.3">3.5.3 <code><nobr>&</nobr></code>: Bitwise AND Operator</a></h4><p><code><nobr>&</nobr></code> provides the bitwise AND operation.<h4><a name="section-3.5.4">3.5.4 <code><nobr><<</nobr></code> and <code><nobr>>></nobr></code>: Bit Shift Operators</a></h4><p><code><nobr><<</nobr></code> gives a bit-shift to the left, justas it does in C. So <code><nobr>5<<3</nobr></code> evaluates to 5times 8, or 40. <code><nobr>>></nobr></code> gives a bit-shift to theright; in NASM, such a shift is <em>always</em> unsigned, so that the bitsshifted in from the left-hand end are filled with zero rather than asign-extension of the previous highest bit.<h4><a name="section-3.5.5">3.5.5 <code><nobr>+</nobr></code> and <code><nobr>-</nobr></code>: Addition and Subtraction Operators</a></h4><p>The <code><nobr>+</nobr></code> and <code><nobr>-</nobr></code>operators do perfectly ordinary addition and subtraction.<h4><a name="section-3.5.6">3.5.6 <code><nobr>*</nobr></code>, <code><nobr>/</nobr></code>, <code><nobr>//</nobr></code>, <code><nobr>%</nobr></code> and <code><nobr>%%</nobr></code>: Multiplication and Division</a></h4><p><code><nobr>*</nobr></code> is the multiplication operator.<code><nobr>/</nobr></code> and <code><nobr>//</nobr></code> are bothdivision operators: <code><nobr>/</nobr></code> is unsigned division and<code><nobr>//</nobr></code> is signed division. Similarly,<code><nobr>%</nobr></code> and <code><nobr>%%</nobr></code> provideunsigned and signed modulo operators respectively.<p>NASM, like ANSI C, provides no guarantees about the sensible operationof the signed modulo operator.<p>Since the <code><nobr>%</nobr></code> character is used extensively bythe macro preprocessor, you should ensure that both the signed and unsignedmodulo operators are followed by white space wherever they appear.<h4><a name="section-3.5.7">3.5.7 Unary Operators: <code><nobr>+</nobr></code>, <code><nobr>-</nobr></code>, <code><nobr>~</nobr></code> and <code><nobr>SEG</nobr></code></a></h4><p>The highest-priority operators in NASM's expression grammar are thosewhich only apply to one argument. <code><nobr>-</nobr></code> negates itsoperand, <code><nobr>+</nobr></code> does nothing (it's provided forsymmetry with <code><nobr>-</nobr></code>), <code><nobr>~</nobr></code>computes the one's complement of its operand, and<code><nobr>SEG</nobr></code> provides the segment address of its operand(explained in more detail in <a href="#section-3.6">section 3.6</a>).
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -