Search code examples
assemblyx86directiveemu8086

Is it necessary to use the keyword ORG in an assembly program?


In some assembly programs it is not necessary to use the ORG directive.

Is there any situation where we must use ORG in our program?
Where would I need to write ORG 100H?


Solution

  • Note: This answer is specific to the usage of ORG in MASM and compatible assemblers. The behaviour explained in this answer doesn't sound very smart in hindsight, so later assemblers like NASM handle repositioning inside the output chunk in a different way.

    The ORG directive serves two different purposes. It can relocate the "current output address" within the currently generated output, for example:

    init_code:
        PUSH CS      ; tiny memory model, even in EXE file
        POP  DS
        MOV  AH,30h
        INT  21h     ; get DOS version
        CMP  AL, 3
        JAE  DOS_new_enough
        MOV  DX, offset error
        MOV  AH, 9
        INT  21h
    error db "Needs DOS 3.0 or newer", 13, 10, '$'
    new_enough:
        ; some program code
    
    ORG init_code
    var1 dw ?
    var2 dw ?
    

    to overlay the variables var1 and var2 over init_code. As init_code will no longer be needed after the DOS version has been checked, that memory can later be reclaimed for different purposes.

    You can also use ORG to assist with self-modifying code, like this:

        MOV [WORD PTR CS:LPT_BASE], 278h  ; LPT2
    ...
        MOV AL, [some_data]
        MOV DX, 378h
        ORG $-2   ; 2 bytes backwards, so the address of the value "378h"
    LPT_BASE DW ?
        OUT DX, AL
    

    These invocations of ORG can be rewritten in different ways.

    Another purpose of ORG is to tell the linker the target offset for the part of a segment in the output file. If there is no ORG directive, the linker just lets the first chunk for a named segment start at offset 0, and each later chunk starts at the end of the previous chunk. Let's say you have two source files assembled separately and then linked together:

    DATA SEGMENT
    my_data db 180h DUP 0
    DATA ENDS
    END
    

    and

    DATA SEGMENT
    my_data2 db 80h DUP 0FFh
    DATA ENDS
    END
    

    The linker will put my_data at offset 0 into the data segment, and my_data2 at offset 180h, so the total data segment size will be 200h.

    Now we could put an ORG directive into the first assembly file, making it look like:

    DATA SEGMENT
        ORG 100h
    my_data db 180h DUP 0
    DATA ENDS
    END
    

    Now, the linker will assign the offset 100h to my_data, and allocate the space between offset 100h and 280h to my_data. my_data2 will be allocated at 280h. The total data segment size is still 200h, but it uses offsets 100h to 300h, instead of 0 to 200h.

    On the other hand, if you use the original first file, and add an ORG 100h directive to the second file, my_data will be allocated at 0, and my_data2 will be forced to be allocated at 100h, overlapping the last 80h bytes of my_data.

    This use of the ORG directive, telling the linker to force placement of segment chunks is not achievable by other means.

    The most common use of ORG is the ORG 100h you cite in your question. You use that directive to tell the assembler/linker system, that the contents of this file are to be loaded at offset 100h in the runtime segment. This is how COM programs in DOS are set up: The first 256 bytes contain management data for the operating system and the command line (which can be re-used as 128-byte data transfer buffer), and the program code starts after it. So ORG 100h forces the toolchain to build a program that fits the memory layout of COM programs.