.NO     New Origin

Syntax:

        .NO  expression1 [,expression2]

See also:

.BS   .DU   .ED   .EP   .OR   .PH   .SM   .TA  

Function:

The .NO directive is very similar to the .OR directive, yet it has some significant differences.

Boundary Sync:

In Version 3 of the SB-Assembler this directive will perform a boundary sync.

Explanation:

The effect of this directive is that the program counter is set to the value of expression1. The way that this is done differs significantly from the way the .OR directive would do that. In principle the .NO directive works identical to the .BS directive. With the .BS directive you specify how big the skipped block of memory should be in terms of the number of bytes. The .NO directive expects you to specify where the skipped block will end by providing the end address in expression1.

Expression1 may not contain forward referenced labels otherwise a fatal Undefined label error will be reported.

The two following program lines will have exactly the same effect when applied to program memory (only true for processors with a traditional 8 bit instruction size):

         .NO  newpc
         .BS  newpc-$

You can determine what should be done with the skipped bytes by supplying the fill value in expression2, just like with the .BS directive.

The value of expression1 may not be less than the current program counter. Values less than the current program counter would otherwise result in very large blocks to be skipped.
The maximum value of expression2 is $FF. Larger values will simply be truncated at the lowest byte before they are used. A value of $100 will fill the skipped memory with the value of $00 for instance.

Operation of the .NO directive differs a little between formatted and unformatted target files.
With unformatted target files a filling value is always used, whether expression2 is given or not. If expression2 is omitted the value $00 is used to fill the skipped memory.
With formatted target files a filling value is only used if expression2 is given. Otherwise the skipped memory block will be skipped completely. The current target buffer will be terminated and a new one is started with the new target address of the address field.
The only exception to this rule is when the number of bytes skipped is less than the line record length of the target file. In that case bytes with the value of $00 are used to fill the skipped memory.

The list file will only contain the first address of the skipped memory block. The filled bytes are not listed in the list file.

Please note that unformatted files rely on the .NO directive to change the program counter because using the .OR directive would close an unformatted file immediately.

Things get a little complicated when you want to skip a certain number of bytes for processors which use multiple bytes per instructions (e.g. PIC and AVR). Some of those processors can store only one byte per instruction word, others can store 2 bytes per instruction word.
That's why I've decided to always fill the skipped code memory for processors which store word sized instructions. That way I'm sure the assembler will always skip the right number of instruction words, whether they store one byte per instruction word or 2.
This doesn't apply to RAM or EEPROM memory though, as these memory types are always byte sized.

Examples:

This is a typical 6502 program to be burned into EPROM. First comes the program together with interrupt routines. Interrupt and reset vectors must be placed at the end of the address space.

         .OR    $F800        Start address of the ROM
NMI      NOP                 The NMI routine
          ;
          ;
          ;
         RTI

IRQ      NOP                 The interrupt request routine
          ;
          ;
          ;
         RTI

RESET    NOP                 The initialization routine
          ;
          ;
          ;
         JMP    AGAIN        End of the program

         .NO    $FFFA,$FF    Skip all unused memory until
;                             the vector space. All skipped
;                             bytes are filled with $FF
         .DA    NMI          The NMI vector
         .DA    RESET        The Reset vector
         .DA    IRQ          The IRQ vector