Skip to main content

IAR Embedded Workbench for Arm 9.70.x

Expressions, operands, and operators

In this section:

Expressions consist of expression operands and operators.

The assembler accepts a wide range of expressions, including both arithmetic and logical operations. All operators use 64-bit two’s complement integers. Range checking is performed if a value is used for generating code.

Expressions are evaluated from left to right, unless this order is overridden by the priority of operators. See also Assembler operators.

These operands are valid in an expression:

  • Constants for data or addresses, excluding floating-point constants

  • Symbols—symbolic names—which can represent either data or addresses, where the latter also is referred to as labels

  • The program location counter (PLC), . (period).

The operands are described in greater details on the following pages.

Note

You cannot have two symbols in one expression, or any other complex expression, unless the expression can be resolved at assembly time. If they are not resolved, the assembler generates an error.

Integer constants

The assembler uses 64-bit two’s complement internal arithmetic, so integers have a (signed) range from -263-1 to 263-1.

Constants are written as a sequence of digits with an optional preceding - (minus) sign in front to indicate a negative number.

Commas and decimal points are not permitted.

The following types of number representation are supported:

Integer type

Example

Binary

1010b, b'1010

Octal

1234q, q'1234

Decimal

1234, -1, d'1234

Hexadecimal

0FFFFh, 0xFFFF, h'FFFF

Table 136. Integer constant formats 


Note

Both the prefix and the suffix can be written with either uppercase or lowercase letters.

ASCII character constants

ASCII constants can consist of any number of characters enclosed in single or double quotes. Only printable characters and spaces can be used in ASCII strings. If the quote character itself will be accessed, two consecutive quotes must be used:

Format

Value

'ABCD'

ABCD (four characters)

"ABCD"

ABCD'\0' (five characters the last ASCII null)

'A''B'

A'B

'A'''

A'

'''' (4 quotes)

'

'' (2 quotes)

Empty string (no value)

"" (2 double quotes)

'\0' (an ASCII null character)

\'

', for quote within a string, as in 'I\'d love to'

\\

\, for \ within a string

\"

", for double quote within a string

Table 137. ASCII character constant formats 


Floating-point constants

The IAR Assembler accepts floating-point values as constants and converts them into IEEE half-precision (16-bit), single-precision (32-bit) or double-precision (64-bit) floating-point format, or fractional format.

Floating-point numbers can be written in the format:

[+|-][digits].[digits][{E|e}[+|-]digits]

This table shows valid examples:

Format

Value

10.23

1.023 x 101

1.23456E-24

1.23456 x 10-24

1.0E3

1.0 x 103

Table 138. Floating-point constants 


Spaces and tabs are not allowed in floating-point constants.

Note

Floating-point constants do not give meaningful results when used in expressions.

True and false

In expressions, a zero value is considered false, and a non-zero value is considered true.

Conditional expressions return the value 0 for false and 1 for true.

Symbols

User-defined symbols can be up to 32,000 characters long, and all characters are significant. Depending on what kind of operation a symbol is followed by, the symbol is either a data symbol or an address symbol where the latter is referred to as a label. A symbol before an instruction is a label and a symbol before, for example the EQU directive, is a data symbol. A symbol can be:

  • absolute—its value is known by the assembler

  • relocatable—its value is resolved at link time.

Symbols must begin with a letter, a–z or A–Z, ? (question mark), or _ (underscore). Symbols can include the digits 0–9 and $ (dollar).

Symbols may contain any printable characters if they are quoted with ` (backquote), for example:

`strange#label`

Case is insignificant for built-in symbols like instructions, registers, operators, and directives. For user-defined symbols, case is by default significant but can be turned on and off using the Case sensitive user symbols (-s) assembler option. For more information, see -s.

Use the symbol control directives to control how symbols are shared between modules. For example, use the PUBLIC directive to make one or more symbols available to other modules. The EXTERN directive is used for importing an untyped external symbol.

Note that symbols and labels are byte addresses. See also Data definition or allocation directives.

Labels

Symbols used for memory locations are referred to as labels.

Program location counter (PLC)

The assembler keeps track of the start address of the current instruction. This is called the program location counter.

To refer to the program location counter in your assembler source code, use the . (period) character. For example:

         section MYCODE:CODE(2)
         arm
         b       .       ; Loop forever
         end

Register symbols

This table shows the predefined register symbols available in 32-bit mode:

Name

Size

Description

CPSR

32 bits

Current program status register

D0-D31

64 bits

Floating-point coprocessor registers for double precision

FPCXT

32 bits

Floating-point context payload

FPEXC

32 bits

Floating-point coprocessor, exception register

FPSCR

32 bits

Floating-point coprocessor, status and control register

FPSID

32 bits

Floating-point coprocessor, system ID register

Q0-Q15

128 bits

Advanced SIMD registers

R0R12

32 bits

General purpose registers

R13 (SP)

32 bits

Stack pointer

R14 (LR)

32 bits

Link register

R15 (PC)

32 bits

Program counter

S0-S31

32 bits

Floating-point coprocessor registers for single precision

SPSR

32 bits

Saved program status register

Table 139. Predefined register symbols in 32-bit mode 


In addition, specific cores might allow you to use other registers, for example APSR for the Cortex-M3, if available in the instruction syntax.

This table shows the predefined register symbols available in 64-bit mode:

Name

Size

Description

X0-X30

64 bits

64 bits in 64-bits general purpose registers R0-R30

W0-W30

32 bits

32 bits in 64-bits general purpose registers R0-R30

SP

64 bits

Stack pointer

WSP

32 bits

Stack pointer

V0-V31

128 bits

128-bit SIMD and floating-point registers V0V31

Q0-Q31

128 bits

128-bit entity in 128-bit SIMD and floating-point registers V0V31

D0-D31

64 bits

Double-precision floating-point in 128-bit SIMD and floating-point registers V0V31

S0-S31

32 bits

Single-precision floating-point in 128-bit SIMD and floating-point registers V0V31

H0-H31

16 bits

Half-precision floating-point in 128-bit SIMD and floating-point registers V0V31

B0-B31

8 bits

8-bit entity in 128-bit SIMD and floating-point registers V0V31

IP0

64 bits

First intra-procedure-call scratch register, alias to R16

IP1

64 bits

Second intra-procedure-call scratch register, alias to R17

FP

64 bits

Frame pointer, alias to R29

LR

64 bits

Link register, alias to R30

XZR

64 bits

Zero 64-bit register

WZR

32 bits

Zero 32-bit register

Table 140. Predefined 64-bit register symbols in 64-bit mode 


Predefined symbols

These predefined symbols are available:

Symbol

Value

__aarch64__

This symbol is defined to 1 when assembling for the A64 instruction set in the AArch64 state.

__ARM_32BIT_STATE

This symbol is defined according to the Arm C Language Extensions (ACLE).

__ARM_64BIT_STATE

This symbol is defined according to the Arm C Language Extensions (ACLE).

__ARM_ADVANCED_SIMD__

An integer that is set based on the ‑‑cpu option. The symbol is set to 1 if the selected processor architecture has the Advanced SIMD architecture extension. The symbol is undefined for other cores.

__ARM_ARCH

This symbol is defined according to the Arm C Language Extensions (ACLE).

__ARM_ARCH_ISA_A64

This symbol is defined according to the Arm C Language Extensions (ACLE).

__ARM_ARCH_ISA_ARM

This symbol is defined according to the Arm C Language Extensions (ACLE).

__ARM_ARCH_ISA_THUMB

This symbol is defined according to the Arm C Language Extensions (ACLE).

__ARM_ARCH_PROFILE

This symbol is defined according to the Arm C Language Extensions (ACLE).

__ARM_BIG_ENDIAN

This symbol is defined according to the Arm C Language Extensions (ACLE).

__ARM_FEATURE_AES

This symbol is defined according to the Arm C Language Extensions (ACLE).

__ARM_FEATURE_CLZ

This symbol is defined according to the Arm C Language Extensions (ACLE).

__ARM_FEATURE_CMSE

An integer that is set based on the assembler option ‑‑cpu and ‑‑cmse. The symbol is set to 3 if the selected processor architecture has CMSE (Cortex-M security extensions) and the assembler option ‑‑cmse is specified.

The symbol is set to 1 if the selected processor architecture has CMSE and the assembler option ‑‑cmse is not specified.

The symbol is undefined for cores without CMSE.

__ARM_FEATURE_CRC32

This symbol is defined to 1 if the CRC32 instructions are supported (optional in Armv8-A/R).

This symbol is defined according to the Arm C Language Extensions (ACLE).

__ARM_FEATURE_CRYPTO

This symbol is defined to 1 if the cryptographic instructions are supported (implies Armv8-A/R with Neon).

This symbol is defined according to the Arm C Language Extensions (ACLE).

__ARM_FEATURE_DIRECTED_ROUNDING

This symbol is defined to 1 if the directed rounding and conversion instructions are supported.

This symbol is defined according to the Arm C Language Extensions (ACLE).

__ARM_FEATURE_DSP

This symbol is defined according to the Arm C Language Extensions (ACLE).

__ARM_FEATURE_FMA

This symbol is defined to 1 if the FPU supports fused floating-point multiply-accumulate.

This symbol is defined according to the Arm C Language Extensions (ACLE).

__ARM_FEATURE_FP16_FML

This symbol is defined according to the Arm C Language Extensions (ACLE).

__ARM_FEATURE_IDIV

This symbol is defined according to the Arm C Language Extensions (ACLE).

__ARM_FEATURE_NUMERIC_MAXMIN

This symbol is defined to 1 if the floating-point numeric maximum and minimum instructions are supported.

This symbol is defined according to the Arm C Language Extensions (ACLE).

__ARM_FEATURE_QBIT

This symbol is defined according to the Arm C Language Extensions (ACLE).

__ARM_FEATURE_QRDMX

This symbol is defined according to the Arm C Language Extensions (ACLE).

__ARM_FEATURE_SAT

This symbol is defined according to the Arm C Language Extensions (ACLE).

__ARM_FEATURE_SHA2

This symbol is defined according to the Arm C Language Extensions (ACLE).

__ARM_FEATURE_SHA3

This symbol is defined according to the Arm C Language Extensions (ACLE).

__ARM_FEATURE_SHA512

This symbol is defined according to the Arm C Language Extensions (ACLE).

__ARM_FEATURE_SIMD32

This symbol is defined according to the Arm C Language Extensions (ACLE).

__ARM_FEATURE_SM3

This symbol is defined according to the Arm C Language Extensions (ACLE).

__ARM_FEATURE_SM4

This symbol is defined according to the Arm C Language Extensions (ACLE).

__ARM_FP

This symbol is defined according to the Arm C Language Extensions (ACLE).

__ARM_MEDIA__

An integer that is set based on the ‑‑cpu option. The symbol is set to 1 if the selected processor architecture has the ARMv6 SIMD extension for multimedia. The symbol is undefined for other cores.

__ARM_MPCORE__

An integer that is set based on the ‑‑cpu option. The symbol is set to 1 if the selected processor architecture has the Multiprocessing Extensions. The symbol is undefined for other cores.

__ARM_NEON

This symbol is defined according to the Arm C Language Extensions (ACLE).

__ARM_NEON_FP

This symbol is defined according to the Arm C Language Extensions (ACLE).

__ARM_PROFILE_M__

An integer that is set based on the ‑‑cpu option. The symbol is set to 1 if the selected processor is a profile M core. The symbol is undefined for other cores.

__ARMVFP__

An integer that is set based on the ‑‑fpu option and that identifies whether floating-point instructions for a vector floating-point coprocessor have been enabled or not. The symbol is defined to __ARMVFPV2__, __ARMVFPV3__, or __ARMVFPV4__. These symbolic names can be used when testing the __ARMVFP__ symbol. If floating-point instructions are disabled (default), the symbol is undefined.

__ARMVFP_D16__

An integer that is set based on the assembler option ‑‑fpu. The symbol is set to 1 if the selected FPU is a VFPv3 or VFPv4 unit with only 16 D registers. Otherwise, the symbol is undefined.

__ARMVFP_FP16__

An integer that is set based on the assembler option ‑‑fpu. The symbol is set to 1 if the selected FPU only supports 16-bit floating-point numbers. Otherwise, the symbol is undefined.

__ARMVFP_SP__

An integer that is set based on the assembler option ‑‑fpu. The symbol is set to 1 if the selected FPU only supports 32-bit single-precision. Otherwise, the symbol is undefined.

__BUILD_NUMBER__

A unique integer that identifies the build number of the assembler currently in use. The build number does not necessarily increase with an assembler that is released later.

__CORE__

An integer that identifies the chip core in use. The value reflects the setting of the assembler option ‑‑cpu. For information about the possible values, see ‑‑cpu.

__DATE__

The current date in dd/Mmm/yyyy format (string).

__FILE__

The name of the current source file (string).

__IAR_SYSTEMS_ASM__

IAR assembler identifier (number). Note that the number could be higher in a future version of the product. This symbol can be tested with #ifdef to detect whether the code was assembled by an assembler from IAR.

__IASMARM__

An integer that is set to 1 when the code is assembled with the IAR Assembler for Arm.

__ilp32__

This symbol is defined to 1 when assembling for the A64 instruction set in the AArch64 state, using the ILP32 data model.

__LINE__

The current source line number (number).

__LITTLE_ENDIAN__

Identifies the byte order in use. Expands to the number 1 when the code is compiled with the little-endian byte order, and to the number 0 when big-endian code is generated. Little-endian is the default.

__lp64__

This symbol is defined to 1 when assembling for the A64 instruction set in the AArch64 state, using the LP64 data model.

__TID__

Target identity, consisting of two bytes (number). The high byte is the target identity, which is 0x4F (=decimal 79) for the IAR Assembler for Arm.

__TIME__

The current time in hh:mm:ss format (string).

__VER__

The version number in integer format, for example, version 6.21.2 is returned as 6021002 (number).

Table 141. Predefined symbols 


Including symbol values in code

Several data definition directives make it possible to include a symbol value in the code. These directives define values or reserve memory. To include a symbol value in the code, use the symbol in the appropriate data definition directive.

For example, to include the time of assembly as a string for the program to display:

            name    timeOfAssembly
            extern  printStr
            section MYCODE:CODE(2)

            adr     r0,time         ; Load address of time
                                    ; string in R0.
            bl      printStr        ; Call string output routine.
            bx      lr              ; Return

            data                    ; In data mode:
time        dc8     __TIME__        ; String representing the
                                    ; time of assembly.
            end
Testing symbols for conditional assembly

To test a symbol at assembly time, use one of the conditional assembly directives. These directives let you control the assembly process at assembly time.

For example, if you want to assemble separate code sections depending on whether you are using an old assembler version or a new assembler version, do as follows:

#if (__VER__ > 6021000)                 ; New assembler version
;…
;…
#else                               ; Old assembler version
;…
;…
#endif

For more information, see Conditional assembly directives.

Absolute and relocatable expressions

Depending on what operands an expression consists of, the expression is either absolute or relocatable. Absolute expressions are those expressions that only contain absolute symbols or relocatable symbols that cancel each other out.

Expressions that include symbols in relocatable sections cannot be resolved at assembly time, because they depend on the location of sections. These are referred to as relocatable expressions.

Such expressions are evaluated and resolved at link time, by the linker. They can only be built up out of a maximum of one symbol reference and an offset after the assembler has reduced it.

For example, a program could define absolute and relocatable expressions as follows:

            name    simpleExpressions
            section MYCONST:CONST(2)
first       dc32    5                ; A relocatable label.
second      equ     10 + 5           ; An absolute expression.

            dc32    first            ; Examples of some legal
            dc32    first + 1        ; relocatable expressions.
            dc32    first + second
            end

Note

At assembly time, there is no range check. The range check occurs at link time and, if the values are too large, there is a linker error.