14

I am curious - What is the difference between .equ and .word directives in ARM assembly, when defining constants?

artless noise
  • 21,212
  • 6
  • 68
  • 105
jhtong
  • 1,529
  • 4
  • 23
  • 34

4 Answers4

23

.equ is like #define in C:

#define bob 10
.equ bob, 10

.word is like unsigned int in C:

unsigned int ted;
ted: 
.word 0

Or initialized with a value:

unsigned int alice = 42;
alice:
.word 42
Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
old_timer
  • 69,149
  • 8
  • 89
  • 168
  • 2
    and it has nothing to do with ARM it is true for most/all platforms supported by gnu assembler and other assemblers with those directives – old_timer Feb 07 '14 at 14:18
  • 1
    Nitpicking :-) 1) `.word is like unsigned int in C`: but it does not set `st_size` as most C compilers, and it can be used anywhere, e.g. on the text section to generate code. 2) `.equ is like #define`: but it also generates an ABS symbol || More details: http://stackoverflow.com/a/33157659/895245 – Ciro Santilli OurBigBook.com Oct 15 '15 at 20:13
  • was just trying to relate to something the OP might understand, like but not exactly like, similar perhaps a better word than like? – old_timer Oct 15 '15 at 21:14
  • Also note that `.word` does *not* create a symbol. So it is rather like `malloc()`, imho. It just reserves a word of anonymous space wherever it appears. You can actually use it to generate instructions if you feel like puzzling together the bits of the opcodes. – Kamajii May 05 '19 at 11:19
  • @Kamajii doesn't .word always allocate 4 bytes of space? – Savannah Madison Jan 30 '21 at 09:45
3

.word is a directive that allocates a word-sized amount of storage space (memory) in that location. It can additionally have that location initialized with a given value.

.equ is more like a C preprocessor #define statement - it gets substituted in any subsequent code.

https://sourceware.org/binutils/docs-2.24/as/Equ.html#Equ

https://sourceware.org/binutils/docs-2.24/as/Word.html#Word

This is not actually ARM-specific, but applies to all gas targets.

unixsmurf
  • 5,852
  • 1
  • 33
  • 40
  • 3
    I just wanted to clarify that you can't use `.word` to initialize variables in RAM...you need something at runtime to do that. –  Feb 07 '14 at 12:51
2

As mentioned in the accepted answer (written by old_timer) label: .word value is like assigning a value to that label. I just want to add that you can assign multiple values to the same label just like an array, as the following:

g_pfnVectors:
  .word  _estack
  .word  Reset_Handler
  .word  NMI_Handler
  .word  HardFault_Handler
  .word  MemManage_Handler
  ...

The previous example has been taken from a STM32 MCU official startup file. This is exactly the machanism to initialize the NVIC.
So g_pfnVectors label got multiple values assigned (as an array, where the values are aligned next to each other in the memory so to say).

Mohammed Noureldin
  • 14,913
  • 17
  • 70
  • 99
-1

NASM 2.10.09 ELF output:

  • .word is simple: it outputs 2 bytes to the object file no matter where we are.

    Consequences of this:

    • if .word is after a symbol x:, x will point to those bytes
    • if .word is in the text segment, those bytes might get executed

    It has absolutely no other side effect. In particular, it does not set the st_size field of the symbol table entry (e.g. int often == 4 bytes), which is something sensible compilers should do. You need the .size x, 2 directive for that.

  • .equ does two things:

    1. updates a macro-like variable
    2. the last time you call it, it generates a symbol with st_shndx == SHN_ABS and the given value

    Sample code:

    .text
    
        .equ x, 123
        mov $x, %eax
        /* eax == 123 */
    
        .equ x, 456
        mov $x, %eax
        /* eax == 456 */
    

    Now:

    as --32 -o main.o main.S
    objdump -Sr main.o
    

    Gives:

    00000000 <.text>:
      0:   b8 7b 00 00 00          mov    $0x7b,%eax
      5:   b8 c8 01 00 00          mov    $0x1c8,%eax
    

    which confirms the macro-like effect, and:

    readelf -s main.o
    

    contains:

    Num:    Value  Size Type    Bind   Vis      Ndx Name
      4: 000001c8     0 NOTYPE  LOCAL  DEFAULT  ABS x
    

    which confirms the SHN_ABS effect: a symbol was created, and it could be used from another file by linking if it were global. I have explained this in more detail at https://stackoverflow.com/a/33148242/895245

    The situation is analogous for NASM's equ, except that the NASM version can only be used once per symbol.

    .set and the equals sign = (source) are the same as .equ.

    You should also look into .equiv https://sourceware.org/binutils/docs-2.25/as/Equiv.html , which prevents redefinition.

Community
  • 1
  • 1
Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985