Search code examples
assemblyx86-64nasm

Does the order in which the labels are defined matter?


I'm trying to create a simple linked list in assembly, but I realized that if I change the order in which I define the labels, the code doesn't display the correct result. So I'm thinking, does the order in which I define the labels matter? Or does the order matter in this isolated case.

Code that works correctly:

%define OFFSET 8
%define SCALE 2

global _start

section .text

x1: 
    dq x2
    dq 48 ;; Zero

x2:
    dq x3
    dq 49 ;; One

x3:
    dq x4
    dq 50 ;; Two

x4:
    dq x5
    dq 51 ;; Three

x5:
    dq 0
    dq 52 ;; Four

end: 
    mov rax, 60
    mov rdi, 0
    syscall

_start:
    mov r8, 0

    .loop:
        mov rax, 1
        mov rdi, 1
        lea rsi, [x1 + r8 * SCALE + OFFSET] 
        mov rdx, 1
        syscall
        
        cmp qword [x1 + r8 * SCALE], 0 
        jz end
        add r8, OFFSET
    jmp .loop    

Code that doesn't work properly (I changed the x1 position):

%define OFFSET 8
%define SCALE 2

global _start

section .text

x2:
    dq x3
    dq 49 ;; One

x3:
    dq x4
    dq 50 ;; Two

x4:
    dq x5
    dq 51 ;; Three

x5:
    dq 0
    dq 52 ;; Four

x1: 
    dq x2
    dq 48 ;; Zero

end: 
    mov rax, 60
    mov rdi, 0
    syscall

_start:
    mov r8, 0

    .loop:
        mov rax, 1
        mov rdi, 1
        lea rsi, [x1 + r8 * SCALE + OFFSET] 
        mov rdx, 1
        syscall
        
        cmp qword [x1 + r8 * SCALE], 0 
        jz end
        add r8, OFFSET
    jmp .loop    


Solution

  • To summarize the comments into an answer proper:

    Does the order in which the labels are defined matter?

    No, the ordering of labels by themselves does not matter keeping in mind

    • (prior NASM version 2.14) a global label declaration must occur before the definition the respective label, and
    • local label definitions shorthand (.my_local_label) is with respect to the most recent global label.

    […] if I change the order in which I define the labels, […] I changed the x1 position […]

    Yes and you have also moved the dq data. There are two changes, not just moving a label location. Just like the order you write down instructions matters, the order of any other data matters too. The textual order (of everything belonging to one section) defines the order in memory.

    I'm trying to create a [singly‑]linked list in assembly […]

    As Jason Harper highlighted, a singly‑linked list means storing and retrieving a (payload, pointer) tuple and following the address pointer indicates.

            lea rsi, [x1 + r8 * SCALE + OFFSET] 
    

    This is a pattern for accessing an array data structure, i. e. a contiguous sequence of Bytes in memory. For a singly‑linked list, you need to retrieve contents from memory and treat the pointer part of the just retrieved data as an address. How does this look like?

        mov rsi, x1
        ; now `rsi` contains _the address_ the label `x1` points to
        
        mov rcx, [rsi + 0]  ; retrieve 8 Bytes located at `rsi`
        mov rsi, [rsi + 8]  ; retrieve 8 Bytes located at `rsi + 8`
    

    Now rcx contains the first eight Bytes at x1 (i. e. the pointer part), so if you use its value

        mov rcx, [rcx]
    

    you have followed a pointer. After this instruction rcx contains the contents found at the memory location the x1 item pointed to (presuming it was not a null‑pointer). I will leave it up to you to wrap everything neatly into a loop.

            cmp qword [x1 + r8 * SCALE], 0 
            jz end
    

    rcx is a nice register to store pointers in because then you can use the jrcxz (jump if rcx is zero) instruction.