Differences between labels and macros in x86_64 assembly language?

Viewed 58

I have little experience in C and Python. In x86_64 assembly language labels are like functions and macros are like functions with more control to me. What are the true differences between labels and macros?

1 Answers

Labels are just human-readable names for offsets and addresses (the distinction depends on the binary format in use).
They are useful not only because they make the source more readable (all addresses look the same, try reverse engineering to see this), but also because their value is computed automatically by the assembler.

Consider this sample snippet:

BITS 64

pow2:
 mov eax, 1 
 test edi, edi
 jz .end
 
.loop:
 add rax, rax
 
 dec edi
 jnz .loop
 
.end:
 ret

and assemble it into a binary file:

> nasm pow2.asm -o pow2

We can opt not to use any labels. In order to do so, we need to track the offset/address of every instruction, so that when we jump we can tell the assembler the right destination.

BITS 64

mov eax, 1      ;5 bytes, offset 0
test edi, edi   ;2 bytes, offset 5
jz SHORT 16     ;2 bytes, offset 7
 
add rax, rax    ;3 bytes, offset 9
dec edi         ;2 bytes, offset 12
jnz SHORT 9     ;2 bytes, offset 14
 
ret             ;1 bytes, offset 16

Not a nice task at all! We need to know the length of every instruction form and we must take great care to make no mistakes or we will introduce a tedious source of very weird bugs.

Nevertheless, the two binaries are the same, showing that labels are just names for numbers.

> nasm pow2_nolabels -o pow2_nolabels
> diff pow2 pow2_nolabels
>

What if we want to change mov eax, 1 with xor eax, eax / inc eax to save 1 byte?
If we are using the labels all we have to do is to change the instruction mov eax, 1, but if we are not, we need to change every target of subsequent jumps.
This simple function already has two, let alone more complex functions.


Macros are an entirely different thing. They are a mechanism for text processing, where the text is the source.
They allow generating structured sources and patterns very quickly, and they can make the code more readable and DRY.

For example, NASM has very powerful macros that can make an assembly program look like a script:

BITS 64

;------ LIBRARY ---------

%define STDOUT 1
%define SYS_WRITE 1
%define SYS_EXIT 60

%macro print 1

SECTION .data
  %%string db %1, 10
  %%string_end:
  
SECTION .text
  mov eax, SYS_WRITE
  mov edi, STDOUT
  lea rsi, [REL %%string]
  mov edx, %%string_end - %%string  ;Assume max 4GiB string
  syscall
  
%endm

%macro exit 1
  mov eax, SYS_EXIT
  mov edi, %1
  syscall
%endm
 
 
;------ PROGRAM --------

GLOBAL _start

_start:
    print "Hello, world!"
    print "Bye"
    exit 0

Note how the program resembles an high level language, where particularly the macro automatically generates the boilerplate code necessary to allocate the string, find its length at assemble time and print it to stdout.
Note also how simple macros like %define are useful for simple text replacement (STDOUT -> 1) to avoid magic constants and make the code readable (both STDOUT and SYSWRITE have value 1 but their meaning is completely different; without the macro we would only find two 1s in the source).

Note that macros are only about source transformation. They are processed at assemble time: when a macro is invoked its body is processed and substituted in the callsite. This is the source after almost all the macros (including the builtin) have been expanded:

[global _start]
_start:

[section .data]
 ..@2.string db "Hello, world!", 10
 ..@2.string_end:

[section .text]
 mov eax, 1
 mov edi, 1
 lea rsi, [REL ..@2.string]
 mov edx, ..@2.string_end - ..@2.string
 syscall

[section .data]
 ..@5.string db "Bye", 10
 ..@5.string_end:

[section .text]
 mov eax, 1
 mov edi, 1
 lea rsi, [REL ..@5.string]
 mov edx, ..@5.string_end - ..@5.string
 syscall

 mov eax, 60
 mov edi, 0
 syscall

See how each macro got expanded into a set of instructions and directives? This is completely different from an ordinary call and, obviously, also totally different from labels.

Related