Table of Contents
NASM, though it attempts to avoid the bureaucracy of assemblers like MASM and TASM, is nevertheless forced to support a few directives. These are described in this chapter.
NASM’s directives come in two types: user-level directives and primitive directives. Typically, each directive has a user-level form and a primitive form. In almost all cases, we recommend that users use the user-level forms of the directives, which are implemented as macros which call the primitive forms.
Primitive directives are enclosed in square brackets; user-level directives are not.
In addition to the universal directives described in this chapter, each object file format can optionally supply extra directives in order to control particular features of that file format. These format-specific directives are documented along with the formats that implement them, in Part IV.
The BITS
directive
specifies whether Yasm should generate code designed to run on a processor operating in
16-bit mode, 32-bit mode, or 64-bit mode. The syntax is BITS
16
, BITS 32
, or BITS
64
.
In most cases, you should not need to use BITS
explicitly. The coff
, elf32
,
macho32
, and win32
object
formats, which are designed for use in 32-bit operating systems, all cause Yasm to select
32-bit mode by default. The elf64
, macho64
, and win64
object formats, which
are designed for use in 64-bit operating systems, both cause Yasm to select 64-bit mode
by default. The xdf
object format allows you to specify each
segment you define as USE16
, USE32
, or USE64
, and Yasm will set its
operating mode accordingly, so the use of the BITS
directive
is once again unnecessary.
The most likely reason for using the BITS
directive is to
write 32-bit or 64-bit code in a flat binary file; this is because the bin
object format defaults to 16-bit mode in anticipation of it being
used most frequently to write DOS .COM
programs, DOS
.SYS
device drivers and boot loader software.
You do not need to specify BITS 32
merely in order to use 32-bit instructions in a 16-bit DOS
program; if you do, the assembler will generate incorrect code because it will be writing
code targeted at a 32-bit platform, to be run on a 16-bit one. However, it is necessary to specify BITS 64
to use 64-bit instructions and registers; this is done to allow use of those instruction
and register names in 32-bit or 16-bit programs, although such use will generate a
warning.
When Yasm is in BITS 16
mode, instructions which use
32-bit data are prefixed with an 0x66 byte, and those referring to 32-bit addresses have
an 0x67 prefix. In BITS 32
mode, the reverse is true: 32-bit
instructions require no prefixes, whereas instructions using 16-bit data need an 0x66 and
those working in 16-bit addresses need an 0x67.
When Yasm is in BITS 64
mode, 32-bit instructions usually
require no prefixes, and most uses of 64-bit registers or data size requires a REX
prefix. Yasm automatically inserts REX prefixes where necessary. There are also 8 more
general and SSE registers, and 16-bit addressing is no longer supported. The default
address size is 64 bits; 32-bit addressing can be selected with the 0x67 prefix. The
default operand size is still 32 bits, however, and the 0x66 prefix selects 16-bit
operand size. The REX prefix is used both to select 64-bit operand size, and to access
the new registers. A few instructions have a default 64-bit operand size.
When the REX prefix is used, the processor does not know how to address the
AH
, BH
, CH
or DH
(high 8-bit legacy) registers.
Instead, it is possible to access the the low 8-bits of the SP
, BP
SI
, and
DI
registers as SPL
,
BPL
, SIL
, and DIL
, respectively; but only when the REX prefix is used.
The BITS
directive has an exactly equivalent primitive
form, [BITS 16]
, [BITS 32]
, and
[BITS 64]
. The user-level form is a macro which has no
function other than to call the primitive form.