The origin directive tells the assembler where to load instructions and data into memory. It changes the program counter to the value specified by the expression in the operand field. Subsequent statements are assembled into memory locations starting with the new program/location counter value. If no ORG directive is encountered in a source program, the program counter is initialized to zero.
Assembler uses an internal variable called LC (Location Counter) to store current offset address of the statement being processed. When it encounters a variable declaration statement, it puts the value of LC in its symbol table as variable’s address.
; Initial value of LC is 0
MOV AX, BX ; Here LC = 0
MOV CX, DX ; Now LC = LC + size of above statement i.e. LC = 0 + 2 = 2
A db 0; ; LC = LC + size of above statement i.e. LC = 2 + 2 = 4.
; So the address of “A” will be 4 as LC = 4 when variable definition appear.
MOV DX, A ; LC = LC + size of above statement i.e. LC = 4 + 1 = 5
; In above statement “A” will be replaced with the address of “A” which is 4.
; At end LC = 5 + 4 = 9
This program will work when it is loaded at offset 0 in the segment pointed by DS register. I.e. loading this program at 200:00h (Segment : Offset) or 700:00h address will work as the offset address is 00h.
What if we need to load this program at 200:300h address? Here DS = 200h and offset = 300h (offset != 0), the variable “A” is physically located at “200:304h” address. But the program will try reading its value from 200:04h address. It is obvious that we will not get expected result as the program is not reading variable from its actual address (200:304h).
This program would have worked if the initial value of LC was 300h. Isn’t it?
So we need a directive which can instruct assembler to initialize LC with a specific value like 300h. The directive “ORG” does this. In such scenarios, we would need to use “ORG XXh” statement at the begging of the program to initialize LC with value XXh.
The bottom line is that we should use “ORG” directive when DS (Data Segment) register is not pointing to the first variable in Data segment (when program has separate Code and Data segment) or first instruction (when program has only one segment for both Code and Data).
This directive is very useful when writing boot loader, device drivers, virus, antivirus and OS components because these programs need to loaded at particular offset address.