NASM does not guarantee the size of the integers used to evaluate expressions at compile time: since NASM can compile and run on 64-bit systems quite happily, don’t assume that expressions are evaluated in 32-bit registers and so try to make deliberate use of ((integer overflow)). It might not always work. The only thing NASM will guarantee is what’s guaranteed by ANSI C: you always have at least 32 bits to work in.
NASM supports two special tokens in expressions,
allowing calculations to involve the current assembly position: the
evaluates to the assembly position at the beginning of the line containing the
expression; so you can code an infinite loop using
$$ evaluates to the beginning of the current section; so you can tell
how far into the section you are by using
<< gives a bit-shift to the left,
just as it does in C. So
5<<3 evaluates to 5 times 8,
>> gives a bit-shift to the right; in NASM,
such a shift is always unsigned, so that the bits
shifted in from the left-hand end are filled with zero rather than a sign-extension of
the previous highest bit.
* is the multiplication operator.
// are both division operators:
/ is unsigned division and
// is signed division. Similarly,
%% provide unsigned and
signed modulo operators
NASM, like ANSI C, provides no guarantees about the sensible operation of the signed modulo operator.
% character is used extensively by the macro
preprocessor, you should ensure that both the signed and unsigned modulo operators are
followed by white space wherever they appear.
The highest-priority operators in NASM’s expression
grammar are those which only apply to one argument.
negates its operand,
+ does nothing (it’s provided for
the one’s complement of
its operand, and
SEG provides the segment address of its operand (explained in more
detail in Section 3.6.8).
When writing large
16-bit programs, which must be split into multiple segments, it is often necessary to be able to refer to
the segment part of the address of a symbol. NASM supports the
SEG operator to perform
mov ax, seg symbol mov es, ax mov bx, symbol
es:bx with a valid pointer to the symbol
Things can be more
complex than this: since 16-bit segments and groups may overlap, you might occasionally want to refer to some symbol
using a different segment base from the preferred one. NASM lets you do this, by the use
WRT (With Reference To) keyword. So you can do things like
mov ax, weird_seg ; weird_seg is a segment base mov es, ax mov bx, symbol wrt weird_seg
es:bx with a different, but functionally
equivalent, pointer to the symbol
NASM supports far (inter-segment) calls and jumps by means of the syntax
call segment:offset, where
offset both represent immediate values. So to call a far
procedure, you could code either of
call (seg procedure):procedure call weird_seg:(procedure wrt weird_seg)
(The parentheses are included for clarity, to show the intended parsing of the above instructions. They are not necessary in practice.)
dw symbol, seg symbol
NASM supports no convenient synonym for this, though you can always invent one using the macro processor.