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
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
global
label declaration must occur before the definition the respective label, and.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.