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?
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?
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.