我试图在汇编中创建一个简单的链表,但我意识到,如果我更改定义标签的顺序,代码将不会显示正确的结果。所以我在想,定义标签的顺序重要吗?或者在这个孤立的案例中顺序是否重要?
正确运行的代码:
%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
无法正常工作的代码(我更改了x1位置):
%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
将评论总结为正确的答案:
定义标签的顺序重要吗?
不,记住标签本身的顺序并不重要
global
标签声明必须出现在之前相应标签的定义,并且.my_local_label
) 是相对于最新的全局标签。[...]如果我更改定义标签的顺序,[...]我更改了x1位置[...]
是的并且您还移动了
dq
数据。
有两个更改,而不仅仅是移动标签位置。
就像您写下指令的顺序很重要一样,任何其他数据的顺序也很重要。
文本顺序(所有属于到一个section
)定义了内存中的顺序。
我正在尝试在程序集中创建一个[单]链接列表[...]
正如 Jason Harper 所强调的,单链表意味着存储和检索(有效负载,指针)元组并遵循地址
pointer
指示。
lea rsi, [x1 + r8 * SCALE + OFFSET]
这是用于访问数组数据结构的模式,即。 e.内存中“连续”的字节序列。
对于单链表,您需要从内存中检索内容并将刚刚检索到的数据的指针部分视为地址。
这看起来怎么样?
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`
rcx
包含x1
处的前八个字节(即指针部分),所以如果你使用
它的值
mov rcx, [rcx]
您已跟随指针。 在此指令之后,
rcx
包含在x1
项指向的内存位置找到的内容(假设它不是空指针)。 我将让您将所有内容整齐地包裹成一个循环。
cmp qword [x1 + r8 * SCALE], 0
jz end
rcx
是一个很好的寄存器来存储指针,因为这样您就可以使用 jrcxz
(如果
rcx
为零则跳转)指令。