Next Chapter | Previous Chapter | Contents | Index
NASM is a portable assembler, designed to be able to compile on any ANSI
C-supporting platform and produce output to run on a variety of Intel x86
operating systems. For this reason, it has a large number of available
output formats, selected using the 
As stated in section 2.1.1,
NASM chooses a default name for your output file based on the input file
name and the chosen output format. This will be generated by removing the
extension (
bin The 
The 
Using the 
ORG The 
For example, the following code will generate the longword
        org     0x100 
        dd      label 
label:
Unlike the 
bin SECTION The 
section .data align=16
switches to the section 
The parameter to 
Multisection The 
progbits nobits progbits .bss nobits align= start= vstart= follows= <section> vfollows= <section> org start vstart align= align=(1 << ALIGN_SHIFT) ALIGN_SHIFT SECTION .text ORG ORG 0 .bss progbits start= vstart= follows= vfollows= section.<secname>.start Map files can be generated in 
obj The 
The 
If your source file contains code before specifying an explicit
When you define a segment in an 
segment data 
dvar:   dw      1234 
segment code 
function: 
        mov     ax,data         ; get segment address of data 
        mov     ds,ax           ; and move it into DS 
        inc     word [dvar]     ; now this reference will work 
        ret
The 
extern  foo 
      mov   ax,seg foo            ; get preferred segment of foo 
      mov   ds,ax 
      mov   ax,data               ; a different segment 
      mov   es,ax 
      mov   ax,[ds:foo]           ; this accesses `foo' 
      mov   [es:foo wrt data],bx  ; so does this
obj SEGMENT The 
segment code private align=16
defines the segment 
The available qualifiers are:
PRIVATE PUBLIC COMMON STACK PRIVATE PUBLIC STACK COMMON ALIGN CLASS CLASS=CODE OVERLAY CLASS USE16 USE32 FLAT FLAT obj SEGMENT SCREEN ABSOLUTE=0xB800 ABSOLUTE ALIGN NASM's default segment attributes are 
GROUP The 
segment data 
        ; some data 
segment bss 
        ; some uninitialized data 
group dgroup data bss
which will define a group called 
If you just refer to 
NASM will allow a segment to be part of more than one group, but will generate a warning if you do this. Variables declared in a segment which is part of more than one group will default to being relative to the first group that was defined to contain the segment.
A group does not have to contain any segments; you can still make
UPPERCASE Although NASM itself is case sensitive, some OMF linkers are not;
therefore it can be useful for NASM to output single-case object files. The
IMPORT The 
The 
    import  WSAStartup wsock32.dll
A third optional parameter gives the name by which the symbol is known in the library you are importing it from, in case this is not the same as the name you wish the symbol to be known by to your code once you have imported it. For example:
    import  asyncsel wsock32.dll WSAAsyncSelect
EXPORT The 
Further parameters can be given to define attributes of the exported symbol. These parameters, like the second, are separated by white space. If further parameters are given, the external name must also be specified, even if it is the same as the internal name. The available attributes are:
resident nodata parm=NNN NNN For example:
    export  myfunc 
    export  myfunc TheRealMoreFormalLookingFunctionName 
    export  myfunc myfunc 1234  ; export by ordinal 
    export  myfunc myfunc resident parm=23 nodata
..start 
obj EXTERN If you declare an external symbol with the directive
    extern  foo
then references such as 
        mov     ax,seg foo      ; get preferred segment base 
        mov     es,ax           ; move it into ES 
        mov     ax,[es:foo]     ; and use offset `foo' from it
This is a little unwieldy, particularly if you know that an external is
going to be accessible from a given segment or group, say
        mov     ax,[foo wrt dgroup]
However, having to type this every time you want to access
    extern  foo:wrt dgroup
This form causes NASM to pretend that the preferred segment base of
This default-
obj COMMON The 
common nearvar 2:near ; `nearvar' is a near common common farvar 10:far ; and `farvar' is far
Far common variables may be greater in size than 64Kb, and so the OMF specification says that they are declared as a number of elements of a given size. So a 10-byte far common variable could be declared as ten one-byte elements, five two-byte elements, two five-byte elements or one ten-byte element.
Some 
common c_5by2 10:far 5 ; two five-byte elements common c_2by5 10:far 2 ; five two-byte elements
If no element size is specified, the default is 1. Also, the
common c_5by2 10:5 ; two five-byte elements common c_2by5 10:2 ; five two-byte elements
In addition to these extensions, the 
common foo 10:wrt dgroup common bar 16:far 2:wrt data common baz 24:wrt data:6
win32 The 
Note that although Microsoft say that Win32 object files follow the
win32 SECTION Like the 
The available qualifiers are:
code text data bss code data bss rdata info info .drectve align= obj The defaults assumed by NASM if you do not specify the above qualifiers are:
section .text code align=16 section .data data align=4 section .rdata rdata align=8 section .bss bss align=4
Any other section name is treated by default like
win32 Among other improvements in Windows XP SP2 and Windows Server 2003
Microsoft has introduced concept of "safe structured exception handling."
General idea is to collect handlers' entry points in designated read-only
table and have alleged entry point verified against this table prior
exception control is passed to the handler. In order for an executable
module to be equipped with such "safe exception handler table," all object
modules on linker command line has to comply with certain criteria. If one
single module among them does not, then the table in question is omitted
and above mentioned run-time checks will not be performed for application
in question. Table omission is by default silent and therefore can be
easily overlooked. One can instruct linker to refuse to produce binary
without such table by passing 
Without regard to this run-time check merits it's natural to expect NASM
to be capable of generating modules suitable for
Former can be easily achieved with any NASM version by adding following line to source code:
$@feat.00 equ 1
As of version 2.03 NASM adds this absolute symbol automatically. If it's not already present to be precise. I.e. if for whatever reason developer would choose to assign another value in source file, it would still be perfectly possible.
Registering custom exception handler on the other hand requires certain
"magic." As of version 2.03 additional directive is implemented,
section .text 
extern  _MessageBoxA@16 
%if     __NASM_VERSION_ID__ >= 0x02030000 
safeseh handler         ; register handler as "safe handler" 
%endif 
handler: 
        push    DWORD 1 ; MB_OKCANCEL 
        push    DWORD caption 
        push    DWORD text 
        push    DWORD 0 
        call    _MessageBoxA@16 
        sub     eax,1   ; incidentally suits as return value 
                        ; for exception handler 
        ret 
global  _main 
_main: 
        push    DWORD handler 
        push    DWORD [fs:0] 
        mov     DWORD [fs:0],esp ; engage exception handler 
        xor     eax,eax 
        mov     eax,DWORD[eax]   ; cause exception 
        pop     DWORD [fs:0]     ; disengage exception handler 
        add     esp,4 
        ret 
text:   db      'OK to rethrow, CANCEL to generate core dump',0 
caption:db      'SEGV',0 
 
section .drectve info 
        db      '/defaultlib:user32.lib /defaultlib:msvcrt.lib '
As you might imagine, it's perfectly possible to produce .exe binary
with "safe exception handler table" and yet engage unregistered exception
handler. Indeed, handler is engaged by simply manipulating
Finally, all mentions of linker in this paragraph refer to Microsoft
linker version 7.x and later. Presence of
win64 The 
win64 While 
        jmp     QWORD[dsptch+rax*8] 
        ... 
dsptch: dq      case0 
        dq      case1 
        ...
Even novice Win64 assembler programmer will soon realize that the code
is not 64-bit savvy. Most notably linker will refuse to link it with
"
        lea     rbx,[rel dsptch] 
        jmp     QWORD[rbx+rax*8]
What happens behind the scene is that effective address in
        lea     rbx,[rel dsptch] 
        add     rbx,QWORD[rbx+rax*8] 
        jmp     rbx 
        ... 
dsptch: dq      case0-dsptch 
        dq      case1-dsptch 
        ...
NASM version 2.03 and later provides another alternative,
        lea     rbx,[rel dsptch] 
        mov     eax,DWORD[rbx+rax*4] 
        sub     rbx,dsptch wrt ..imagebase 
        add     rbx,rax 
        jmp     rbx 
        ... 
dsptch: dd      case0 wrt ..imagebase 
        dd      case1 wrt ..imagebase
One can argue that the operator is redundant. Indeed, snippet before
last works just fine with any NASM version and is not even Windows
specific... The real reason for implementing
It should be noted that 
        dd      label wrt ..imagebase           ; ok 
        dq      label wrt ..imagebase           ; bad 
        mov     eax,label wrt ..imagebase       ; ok 
        mov     rax,label wrt ..imagebase       ; bad
win64 Structured exception handing in Win64 is completely different matter
from Win32. Upon exception program counter value is noted, and
linker-generated table comprising start and end addresses of all the
functions [in given executable module] is traversed and compared to the
saved program counter. Thus so called 
While majority of subroutines written in assembler are not calling any
other function, requirement for non-volatile registers' immutability leaves
developer with not more than 7 registers and no stack frame, which is not
necessarily what [s]he counted with. Customarily one would meet the
requirement by saving non-volatile registers on stack and restoring them
upon return, so what can go wrong? If [and only if] an exception is raised
at run-time and no 
Now, when we understand significance of the
As for the moment of this writing NASM unfortunately does not facilitate generation of above mentioned detailed information about stack frame layout. But as of version 2.03 it implements building blocks for generating structures involved in stack unwinding. As simplest example, here is how to deploy custom exception handler for leaf function:
default rel 
section .text 
extern  MessageBoxA 
handler: 
        sub     rsp,40 
        mov     rcx,0 
        lea     rdx,[text] 
        lea     r8,[caption] 
        mov     r9,1    ; MB_OKCANCEL 
        call    MessageBoxA 
        sub     eax,1   ; incidentally suits as return value 
                        ; for exception handler 
        add     rsp,40 
        ret 
global  main 
main: 
        xor     rax,rax 
        mov     rax,QWORD[rax]  ; cause exception 
        ret 
main_end: 
text:   db      'OK to rethrow, CANCEL to generate core dump',0 
caption:db      'SEGV',0 
 
section .pdata  rdata align=4 
        dd      main wrt ..imagebase 
        dd      main_end wrt ..imagebase 
        dd      xmain wrt ..imagebase 
section .xdata  rdata align=8 
xmain:  db      9,0,0,0 
        dd      handler wrt ..imagebase 
section .drectve info 
        db      '/defaultlib:user32.lib /defaultlib:msvcrt.lib '
What you see in 
As already mentioned, in Win64 terms leaf function is one that does not
call any other function nor modifies any non-volatile register,
including stack pointer. But it's not uncommon that assembler programmer
plans to utilize every single register and sometimes even have variable
stack frame. Is there anything one can do with bare building blocks? I.e.
besides manually composing fully-fledged
function: 
        mov     rax,rsp         ; copy rsp to volatile register 
        push    r15             ; save non-volatile registers 
        push    rbx 
        push    rbp 
        mov     r11,rsp         ; prepare variable stack frame 
        sub     r11,rcx 
        and     r11,-64 
        mov     QWORD[r11],rax  ; check for exceptions 
        mov     rsp,r11         ; allocate stack frame 
        mov     QWORD[rsp],rax  ; save original rsp value 
magic_point: 
        ... 
        mov     r11,QWORD[rsp]  ; pull original rsp value 
        mov     rbp,QWORD[r11-24] 
        mov     rbx,QWORD[r11-16] 
        mov     r15,QWORD[r11-8] 
        mov     rsp,r11         ; destroy frame 
        ret
The keyword is that up to 
EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, 
        CONTEXT *context,DISPATCHER_CONTEXT *disp) 
{   ULONG64 *rsp; 
    if (context->Rip<(ULONG64)magic_point) 
        rsp = (ULONG64 *)context->Rax; 
    else 
    {   rsp = ((ULONG64 **)context->Rsp)[0]; 
        context->Rbp = rsp[-3]; 
        context->Rbx = rsp[-2]; 
        context->R15 = rsp[-1]; 
    } 
    context->Rsp = (ULONG64)rsp; 
 
    memcpy (disp->ContextRecord,context,sizeof(CONTEXT)); 
    RtlVirtualUnwind(UNW_FLAG_NHANDLER,disp->ImageBase, 
        dips->ControlPc,disp->FunctionEntry,disp->ContextRecord, 
        &disp->HandlerData,&disp->EstablisherFrame,NULL); 
    return ExceptionContinueSearch; 
}
As custom handler mimics leaf function, corresponding
coff The 
The 
macho The 
elf, elf32, and elf64 The 
osabi The ELF header specifies the application binary interface for the target
operating system (OSABI). This field can be set by using the
elf SECTION Like the 
The available qualifiers are:
alloc noalloc exec noexec write nowrite progbits nobits align= obj The defaults assumed by NASM if you do not specify the above qualifiers are:
section .text progbits alloc exec nowrite align=16 section .rodata progbits alloc noexec nowrite align=4 section .data progbits alloc noexec write align=4 section .bss nobits alloc noexec write align=4 section other progbits alloc noexec nowrite align=1
(Any section name other than 
elf WRT The 
Since 
wrt ..gotpc _GLOBAL_OFFSET_TABLE_ $$ wrt ..gotoff wrt ..got wrt ..plt CALL JMP wrt ..sym A fuller explanation of how to use these relocation types to write shared libraries entirely in NASM is given in section 9.2.
elf GLOBAL 
You can specify whether a global variable is a function or a data object
by suffixing the name with a colon and the word
global hashlookup:function, hashtable:data
exports the global symbol 
Optionally, you can control the ELF visibility of the symbol. Just add
one of the visibility keywords: 
global hashlookup:function hidden
You can also specify the size of the data associated with the symbol, as a numeric expression (which may involve labels, and even forward references) after the type specifier. Like this:
global  hashtable:data (hashtable.end - hashtable) 
hashtable: 
        db this,that,theother  ; some data here 
.end:
This makes NASM automatically calculate the length of the table and
place that information into the 
Declaring the type and size of global symbols is necessary when writing shared library code. For more information, see section 9.2.4.
elf COMMON 
common dwordarray 128:4
This declares the total size of the array to be 128 bytes, and requires that it be aligned on a 4-byte boundary.
The 
aout a.out The 
aoutb a.out The 
as86 as86 The Minix/Linux 16-bit assembler 
NASM supports this format, just in case it is useful, as
rdf The 
The Unix NASM archive, and the DOS archive which includes sources, both
contain an 
LIBRARY 
    library  mylib.rdl
MODULE Special 
    module  mymodname
Note that when you statically link modules and tell linker to strip the
symbols from output file, all module names will be stripped too. To avoid
it, you should start module names with 
    module  $kernel.core
rdf GLOBAL 
Suffixing the name with a colon and the word
    global  sys_open:export
To specify that exported symbol is a procedure (function), you add the
word 
    global  sys_open:export proc
Similarly, to specify exported data object, add the word
    global  kernel_ticks:export data
rdf EXTERN By default the 
    library $libc 
    extern  _open:import 
    extern  _printf:import proc 
    extern  _errno:import data
Here the directive 
dbg The 
The 
For simple files, one can easily use the 
nasm -f dbg filename.asm
which will generate a diagnostic file called
nasm -e -f rdf -o rdfprog.i rdfprog.asm nasm -a -f dbg rdfprog.i
This preprocesses 
This workaround will still typically not work for programs intended for