9.2 Assembly expressions

Expressions consist of one or more integer literals or symbol references, combined using operators.

You can use an expression when an instruction operand or directive argument expects an integer value or label.

Not all instruction operands and directive arguments accept all possible expressions. For example, the alignment directives require an absolute expression for the boundary to align to. Therefore, alignment directives cannot accept expressions involving labels, but can accept expressions involving only integer constants.

On the other hand, the data definition directives can accept a wider range of expressions, including references to defined or undefined symbols. However, the types of expressions accepted is still limited by the ELF relocations available to describe expressions involving undefined symbols. For example, it is not possible to describe the difference between two symbols defined in different sections. The assembler reports an error when an expression is not valid in the context in which it is used.

Expressions involving integer constants are evaluated as signed 64-bit values internally to the assembler. If an intermediate value in a calculation cannot be represented in 64 bits, the behavior is undefined. The assembler does not currently emit a diagnostic when this happens.

Constants

Numeric literals are accepted in the following formats:

  • Decimal integer in range 0 to (264)-1.
  • Hexadecimal integer in range 0 to (264)-1, prefixed with 0x.
  • Octal integer in range 0 to (264)-1, prefixed with 0.
  • Binary integer in range 0 to (264)-1, prefixed with 0b.

Some directives accept values larger than (264)-1. These directives only accept simple integer literals, not expressions.

Note:

These ranges do not include negative numbers. Negative numbers can instead be represented using the unary operator, -.

Symbol References

References to symbols are accepted as expressions. Symbols do not need to be defined in the same assembly language source file, to be referenced in expressions.

The period symbol (.) is a special symbol that can be used to reference the current location in the output file.

For AArch32 targets, a symbol reference might optionally be followed by a modifier in parentheses. The following modifiers are supported:

Table 9-1 Modifiers

Modifier Meaning
None Do not relocate this value.
got_pre1 Offset from this location to the GOT entry of the symbol.
target1 Defined by platform ABI.
target2 Defined by platform ABI.
plel31 Offset from this location to the symbol. Bit 31 is not modified.
sbrel Offset to symbol from addressing origin of its output segment.
got Address of the GOT entry for the symbol.
gotoff Offset from the base of the GOT to the symbol.

Operators

The following operators are valid expressions:

Table 9-2 Unary operators

Unary operator Meaning
-expr Arithmetic negation of expr.
+expr Arithmetic addition of expr.
~expr Bitwise negation of expr.

Table 9-3 Binary operators

Binary operator Meaning
expr1 - expr2 Subtraction.
expr1 + expr2 Addition.
expr1 * expr2 Multiplication.
expr1 / expr2 Division.
expr1 % expr2 Modulo.

Table 9-4 Binary logical operators

Binary logical operator Meaning
expr1 && expr2 Logical and. 1 if both operands non-zero, 0 otherwise.
expr1 || expr2 Logical or. 1 if either operand is non-zero, 0 otherwise.

Table 9-5 Binary bitwise operators

Binary bitwise operator Meaning
expr1 & expr2 expr1 bitwise and expr2.
expr1 | expr2 expr1 bitwise or expr2.
expr1 ^ expr2 expr1 bitwise exclusive-or expr2.
expr1 >> expr2 Logical shift right expr1 by expr2 bits.
expr1 << expr2 Logical shift left expr1 by expr2 bits.

Table 9-6 Binary comparison operators

Binary comparison operator Meaning
expr1 == expr2 expr1 equal to expr2.
expr1 != expr2 expr1 not equal to expr2.
expr1 < expr2 expr1 less than expr2.
expr1 > expr2 expr1 greater than expr2.
expr1 <= expr2 expr1 less than or equal to expr2.
expr1 >= expr2 expr1 greater than or equal to expr2.

The order of precedence for binary operators is as follows, with highest precedence operators listed first:

  1. *, /, %, >>, <<
  2. |, ^, &
  3. +, -
  4. ==, !=, <, >, <=, >=
  5. &&
  6. ||

Operators listed on the same line have equal precedence, and are evaluated from left to right. All unary operators have higher precedence than any binary operators.

Note:

The precedence rules for assembler expressions are not identical to those for C.

Relocation specifiers

For some instruction operands, a relocation specifier might be used to specify which bits of the expression should be used for the operand, and which type of relocation should be used.

These relocation specifiers can only be used at the start of an expression. They can only be used in operands of instructions that support them.

In AArch32 state, the following relocation specifiers are available:

Table 9-7 Relocation specifiers for AArch32 state

Relocation specifier Meaning
:lower16: Use the lower 16 bits of the expression value.
:upper16: Use the upper 16 bits of the expression value.

These relocation specifiers are only valid for the operands of the movw and movt instructions. They can be combined with an expression involving the current place to create a place-relative relocation, and with the sbrel symbol modifier to create a static-base-relative relocation. The current place is the location that the assembler is emitting code or data at. A place-relative relocation is a relocation that generates the offset from the relocated data to the symbol it references.

In AArch64 state, the following relocation specifiers are available:

Table 9-8 Relocation specifiers for AArch64 state

Relocation specifier Relocation type Bits to use Overflow checked
:lo12: Absolute [11:0] No
:abs_g3: Absolute [63:48] Yes
:abs_g2: Absolute [47:32] Yes
:abs_g2_s: Absolute, signed [47:32] Yes
:abs_g2_nc: Absolute [47:32] No
:abs_g1: Absolute [31:16] Yes
:abs_g1_s: Absolute, signed [31:16] Yes
:abs_g1_nc: Absolute [31:16] No
:abs_g0: Absolute [15:0] Yes
:abs_g0_s: Absolute, signed [15:0] Yes
:abs_g0_nc: Absolute [15:0] No
:got: Global Offset Table Entry [32:12] Yes
:got_lo12: Global Offset Table Entry [11:0] No

These relocation specifiers can only be used in the operands of instructions that have matching relocations defined in ELF for the Arm 64-bit Architecture (AArch64). They can be combined with an expression involving the current place to create a place-relative relocation.

Examples

      // Using an absolute expression in an instruction operand:
      orr r0, r0, #1<<23

      // Using an expression in the memory operand of an LDR instruction to
      // reference an offset from a symbol.
    func:
      ldr r0, #data+4 // Will load 2 into r0
      bx lr
    data:
      .word 1
      .word 2

      // Creating initialized data that contains the distance between two
      // labels:
    size:
      .word end - start
    start:
      .word 123
      .word 42
      .word 4523534
    end:

      // Load the base-relative address of 'sym' (used for 'RWPI'
      // position-independent code) into r0 using movw and movt:
      movw r0, #:lower16:sym(sbrel)
      movt r0, #:upper16:sym(sbrel)

      // Load the address of 'sym' from the GOT using ADRP and LDR (used for
      // position-independent code on AArch64):
      adrp x0, #:got:sym
      ldr x0, [x0, #:got_lo12:sym]

      // Constant pool entry containing the offset between the location and a
      // symbol defined elsewhere. The address of the symbol can be calculated
      // at runtime by adding the value stored in the location of the address
      // of the location. This is one technique for writing position-
      // independent code, which can be executed from an address chosen at
      // runtime without re-linking it.
      adr r0, address
      ldr r1, [r0]
      add r0, r0, r1
    address:
      .word extern_symbol - .
Non-ConfidentialPDF file icon PDF versionDUI0774J
Copyright © 2014–2017, 2019 Arm Limited or its affiliates. All rights reserved.