VMS Help  —  MACRO  /ALPHA  Label Addresses
    In the absence of optimization and automatic data alignment,
    label addresses are defined to be the psect and offset of the
    current location counter at the point where the label is defined.
    When either optimization or automatic data alignment are enabled,
    the following additional considerations apply.

1  –  Label Addresses, Optimization, and Code Alignment

    Optimization and code alignment can affect the addresses
    assigned to labels defined in psects that have the EXE and NOMIX
    attributes. Optimization and code alignment are disabled by
    default, and can be enabled with the /OPTIMIZE and /ALIGNMENT
    command-line qualifiers and the .ENABLE directive In general, the
    assembler assigns the psect and offset of the current location
    counter before optimization or alignment of code labels. However,
    the assembler adjusts references to labels in branch instructions
    to the address of the label after optimization and code alignment
    processing. The assembler does not adjust references to labels
    where the label reference occurs in an expression with more than
    one term. The following example shows this:

            .PSECT CODE, EXE, NOMIX
            BSR     R0, 10$            ; R0 -> 10$ (postoptimization)
    10$:    LDA     R1, 20$-10$(R0)    ; R1 -> 20$ (preoptimization)
            JMP     (R1)
            [...]
    20$:

    In the previous example, the assembler adjusts the target
    address of the BSR instruction to be the location of 10$ after
    optimization and code alignment have taken place. Thus, the
    branch to 10$ functions as expected. However, when processing the
    LDA instruction, the assembler computes the offset between 20$
    and 10$ before optimization and code alignment. Thus, the address
    of 20$ that is stored in R1 is the address prior to optimization
    and code alignment. Depending on the sequence of instructions
    between 10$ and 20$, the address before optimization and code
    alignment may differ from the address after optimization and code
    alignment and the JMP instruction may not transfer control to the
    expected address.

    Note also that the assembler only performs postoptimization
    adjustment of label addresses when the label is the only term
    in the expression. For example:

            .PSECT CODE, EXE, NOMIX
            .BASE R27,LINKAGE
            LDQ     R26, ROUTINE1_ADDR
            JSR     R26, (R26)
            LDQ     R26, ROUTINE2_ADDR
            JSR     R26, (R26)
            RET     R28
            NOP
            NOP

    ROUTINE1:
            RET     (R26)
    ROUTINE2:
            RET     (R26)

            .PSECT LINKAGE, NOEXE
    LINKAGE:
    ROUTINE1_ADDR:
            .ADDRESS ROUTINE1
    ROUTINE2_ADDR:
            .ADDRESS ROUTINE2+0

    In the previous example, the assembler adjusts the address stored
    with the .ADDRESS ROUTINE1 directive to the address of label
    ROUTINE1 after optimization and code alignment. However, since
    the expression in the .ADDRESS ROUTINE2+0 directive is not a
    single term, the assembler adds the offset 0 and the address
    of ROUTINE2 before optimization and code alignment and stores
    the result. Since the address stored is the address before
    optimization and code alignment, the second JSR instruction may
    not transfer control to the address that is expected.

2  –  Label Addresses and Automatic Data Alignment

    Automatic data alignment can affect the addresses assigned to
    labels in psects that have the NOEXE or MIX attributes. Automatic
    data alignment is enabled with the .ENABLE ALIGN_DATA directive
    or the /ALIGNMENT=data command-line option.

    A label that occurs in a statement with a data-storage directive
    is assigned the psect and offset of the storage allocated by the
    data-storage directive. If the data-storage directive requires
    automatic alignment, the address is assigned to the label after
    automatic alignment.

    The same is true of labels that occur in statements by themselves
    and that are followed by a data directive in a subsequent
    statement. However, if a label occurs in a statement by itself
    and is followed by a statement that is not a data-storage
    directive, a macro directive, a conditional directive, or a
    lexical-string symbol assignment, the label is assigned the psect
    and offset of the current location counter before any automatic
    alignment.

    The assembler only assigns addresses to labels after alignment
    under the conditions previously described and only with automatic
    alignment. If you place a label before a .ALIGN directive that
    manually aligns the current location counter, the assembler
    assigns the address of the label before performing the manual
    alignment. The following example shows the interaction of label
    address assignment and automatic data alignment:

        .ENABLE ALIGN_DATA
        .PSECT DATA, NOEXE
        .BYTE   1       ; The byte is stored in psect data at offset 0
    A:  .PRINT "Not aligned" ; Any non-macro, nonconditional
                        ; statement, including this .PRINT directive
                 ; prevents A from being automatically aligned
                        ; -- A is assigned offset 1
    B:                  ; B is automatically aligned to offset 4
    C:  .LONG   2       ; C is automatically aligned to offset 4
    D:  .ALIGN 0        ; The .ALIGN global directive prevents D
                        ;  from being automatically aligned --
          ;  D is assigned offset 8
    E:  .OCTA 3         ; E is automatically aligned to offset 16

    Automatic data alignment and label-address assignment can be an
    important consideration when calculating the difference between
    two labels. For example, consider the following macro, which
    stores a string preceded by a word that contains the string's
    length:

            .MACRO VARYING_STRING STRING ?L1, ?L2
                    .WORD L2-L1
                L1: .ASCII "STRING"
                L2:
            .ENDM VARYING_STRING

    If an invocation of the VARYING_STRING macro is followed by a
    data-storage directive that requires automatic alignment, the
    VARYING_STRING macro will not store the correct string length.
    For example:

            .PSECT DATA, NOEXE, .OCTA
            .ENABLE ALIGN_DATA
            VARYING_STRING <Time for something sweet!> ; 25 bytes
    F:      .OCTA 4

    In this example, the intention is to make the L2 label generated
    by the VARYING_STRING macro be assigned the offset 27, 2 for
    the .WORD directive, plus 25 for the .ASCII directive. Instead,
    it is assigned the offset 32 along with the label F because
    the .OCTA directive requires automatic alignment to offset 32.
    Therefore, the string length is incorrectly stored as 30 rather
    25. To make this macro work as desired, you must include, in the
    macro definition, a macro directive that is not a data-storage,
    macro, or conditional directive after the generated label L2. In
    the following example, .ALIGN 0 is a good choice as it reflects
    the idea that the preceding label is not aligned:

     .MACRO VARYING_STRING STRING ?L1, ?L2
          .WORD L2-L1
         L1: .ASCII "STRING"
         L2: .ALIGN 0
     .ENDM VARYING_STRING

    With this change, the generated label L2 is assigned the offset
    27 before the assembler performs automatic data alignment for the
    .OCTA directive. As a result, the VARYING_STRING macro works as
    desired and stores the correct string length of 25.
Close Help