How to use the directives ORG and SECTION with NASM

Reference picture of the post "How to use the directives ORG and SECTION with NASM"

In this post, I write about my first baby steps with NASM, which is a complex tool that can output many different formats. Depending on the output format, the syntax of NASM changes a little bit. For instance, the directive ORG is legal only in combination with the option -f bin which instructs NASM to produce a pure binary file in output. Additionally, I discovered how the directive SECTION assumes a slightly different meaning depending on the used option for output: either -f bin or -f obj (which produces a 16-bit Object Module file as the option /omf of MASM). I understood how I could take advantage of the flat binary output format of NASM to produce my SOFTWARE.BIG1 without the need of any linker. I summarize here my experience in three main steps:

How to use the directives ORG and SECTION with NASM

MASM and NASM both have a directive ORG but the effects in the creation of the assembled output are different. I am not going to present the differences among MASM and NASM about the ORG directive, but just write about what the ORG directive is and how to use it in the contest of NASM. The function of the ORG directive is to specify the origin address which NASM will assume the program begins at when it is loaded into memory. Its sole function is to specify one offset which is added to all internal address references within the section unless one redefines the section with a vstart= option (ahead in this post, I clarify aspects of this sentence with examples, so try to remember it).
There are three important features to remember about ORG:

  1. ORG can be used only one time in the whole source code;
  2. ORG can be placed anywhere in the source code (but only once);
  3. ORG can be used only with -f bin output file format.

The function of the directive SECTION is to define and organize blocks or sections of the binary output file. The NASM's authors write that the directive SECTION is synonymous for the MASM directive SEGMENT2, but this is not what it seems to me when I use it. I can use the directive SECTION to define segments (as I am going to demonstrate in the post "How to make a SOFTWARE.BIG") but this is just one of the different possible way of using it. Moreover the syntax and the usage of the directive SECTION in NASM changes depending on the used option for output: either -f bin or -f obj:

  • -f bin: SECTION can have additional parameters such as align=, start= and vstart=
  • -f obj: SECTION can have other additional parameters such as PRIVATE, PUBLIC, COMMON, STACK, align, use16, use32 etc.

In case of -f obj, the directive SECTION and SEGMENT appears to me to be like synonymous and they both behave in the same way in NASM (probably this is the aspect that the authors of NASM refer to when they write that SECTION and SEGMENT are synonymous).

At this point, I want to show my experience made with the directives ORG and SECTION.

The file: "Learn NASM - 00.lst"
1 ;############################################################################## 2 ; Learn NASM - 00.asm 3 ; 4 ; 5 ; Build with: 6 ; nasm -f bin "Learn NASM - 00.asm" -l "Learn NASM - 00.lst" 7 ;############################################################################## 8 9 10 11 org 0x7c00 ; The function of the ORG directive is to specify 12 ; the origin address which NASM will assume 13 ; the program begins at when it is loaded 14 ; into memory. Its sole function is to specify one 15 ; offset which is added to all internal address 16 ; references within the section (section) unless 17 ; one redefine the section with a vstart= option. 18 ; 19 ; IMPORTANT!!! 20 ; -> org can be used only one time in the whole 21 ; source code. 22 ; -> org can be placed anywhere in the source code 23 ; (but only once). 24 ; -> org can be used only with -f bin output file 25 ; format (it is not the same as in MASM). 26 27 00000000 112233 db 0x11, 0x22, 0x33 28 29 ;############################################################################## 30 ; Full definition of section IN COMBINATION WITH -f bin !!! 31 ; 32 ; Sections can be aligned at a specified boundary following the previous 33 ; section with align=, or at an arbitrary byte-granular position with start=. 34 ; 35 ; align= -> can be any power of 2. 36 ; start= -> is a flat address (example: 0x01_7C00) where the section starts 37 ; in memory. 38 ; vstart= -> the virtual start address, which will be used for the calculation 39 ; of all memory references within that section (section) 40 ;############################################################################## 41 section red start=0x7c10 42 section blue start=0x7c50 vstart=0x0300 43 44 45 section red 46 MsgOne: 47 00000000 6369616F db 'ciao' 48 00000004 B8[0000] mov ax, MsgOne 49 50 51 section blue 52 MsgTwo: 53 00000000 68656C6C6F db 'hello' 54 00000005 B8[0000] mov ax, MsgTwo 55 56 57 section red 58 MsgTree: 59 00000007 73616C7574 db 'salut' 60 0000000C B8[0700] mov ax, MsgTree

I created an initial file "Learn NASM - 00.asm", then I assembled it with NASM using the command: nasm -f bin "Learn NASM - 00.asm" -l "Learn NASM - 00.lst". I did changes and looked at the effects in the list file "Learn NASM - 00.lst" and in the binary one "Learn NASM - 00"3. In the version that I present here, you can see the ORG directive at line 11. At line 27, I placed 3 bytes 0x11, 0x22 and 0x33 just to have a visual reference. As you can tell by looking at the left side of the same line, NASM starts assembling them at address 0x00. At lines 41 and 42, I defined two section with arbitrary names: "red" and "blue". I said that the section red started at 0x7C10 and the section blue started at 0x7C50. Additionally, I set the virtual start of addresses at 0x0300 for the blue section (vstart=0x03004). I mentioned already that the vstart= option resets the address counter that was set with the ORG directive and I am about to show it now.

Continuing in the program, I wrote the MsgOne and I referenced it at line 47 with the MNEMONIC mov ax, MsgOne. I would like you to observe the OPCODE at line 47 (0xB80000) which has an offset of 0x00 from the beginning of the section red. In fact, at the first glance that NASM gave to the program, it saw the message MsgOne that started immediately at the beginning of the section red. You can observe the same story at line 54, with the MsgTwo of section blue. Finally, I switched back again to the section red and I placed MsgTree which was referenced at address 0x07 from the start of the red section. NASM let the programmer switch from section to section in a very easy way, as you can tell by the way I wrote the program from line 45 onwards. I use to declare the section all at the beginning (like lines 41 and 42) because this (almost) fixes already the order by which the sections appears in the binary file. More precisely: NASM organizes the different sections in the binary file depending on the value passed to the option start= or by the chronologic order by which the section declaration appears in the source file if the start= option were not specified.

Fig. A - The binary file "Learn NASM - 00"
Fig. A - The binary file "Learn NASM - 00"

In Fig. A, you see the binary file which started at address 0x00, but it is supposed to appear in memory at address 0x7C00. At least this is what I said to NASM when I wrote the directive ORG 0x7C00. At the address 0x10 of the binary file (which corresponds to 0x7c00 + 0x10 in the calculation that NASM did considering the ORG directive) you see the section red. Similarly, at address 0x50 of the binary file (0x7c00 + 0x50) you see the section blue. If you try to put what you see here together with the lines 41 and 42 of the list file and the options start=0x7C10 and start=0x7C50, you should be able to make sense of it. In my intention, this should explain the sentence wrote previously: "Its sole function (the ORG directive) is to specify one offset which is added to all internal address references [...]".

Now, I want you to observe the OPCODES of the two move instructions (0xB8107C and 0xB8177C) and compare them with the OPCODES in the list file at lines 48 and 60. As you can see, the addresses in the binary files are equal to the addresses calculated in the list file plus the start of the section. But what happened with the OPCODE 0xB80003 (marked in blu in Fig. A at address 0x55 in the binary file)? The MsgTwo started at a relative offset of 0x00 Bytes from the begin of the blue section (see the OPCODE in the list file at line 54) but I declared a virtual start for the addresses of the blue section at 0x0300 when I used the option vstart=0x0300 at line 42. In my intention, this should explain the effect of the option vstart= and explain the sentence wrote previously: "[...] unless one redefine the section with a vstart= option [...]".

Finally, I want you to observe that, regardless the way I switched among sections in the program (lines 41, 42, 45, 51 and 57 of the list file), NASM groups the Bytes belonging to a section altogether and places the sections in the order specified by the start= option. If no start= option is available, then NASM places the section immediately following the end of the previous one, with as many Bytes of alignment, from the end of the previous section, as specified in the option align= (if the align= option is not available, NASM aligns at boundary of paragraph).

This concludes, for the moment, the initial understanding of the directives ORG and SECTION, but I am going to continue on the same topic in the next upcoming posts.



  1. SOFTWARE.BIG is the 16-bit binary image file that, once on the root of TEST partition, is loaded in RAM and executed by my bootloader SHUTTLE2. You can read all the story about my bootloader SHUTTLE2 in the chapter VI. [click back]
  2. See Chapter 7.3 "SECTION or SEGMENT: Changing and Defining Sections" of the NASM documentation. [click back]
  3. I suggest you to do the same and develop a feeling of what happens to the binary file when you do changes in the .asm file. [click back]
  4. Take care of writing exactly vstart=0x0300 and not vstart = 0x0300 with any space in between, otherwise NASM considers it as an error. The same is also valid for the options align= and start=. Yes, it seems strange to me too, why it has to be like that.... [click back]

<PREV.  -  ALL  -  NEXT>

Comments