1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
%ifndef LINKED_LIST_INC
%define LINKED_LIST_INC
%ifndef ALLOC_INC
%include "alloc.inc"
%endif
struc LinkedListNode
ll_next: resq 1
ll_value: resq 1
endstruc
struc DoublyLinkedListNode
dll_next: resq 1
dll_prev: resq 1
dll_value: resq 1
endstruc
%macro lln_alloc 0
alloc LinkedListNode_size
mov qword [rax + ll_next], 0
%endmacro
%macro dll_alloc 0
alloc DoublyLinkedListNode_size
mov qword [rax + dll_next], 0
mov qword [rax + dll_prev], 0
%endmacro
%macro lln_free 0-1 rax
free %1, LinkedListNode_size
%endmacro
%macro dll_free 0-1 rax
free %1, DoublyLinkedListNode_size
%endmacro
%macro ll_seek 0-1 rax
mov rax, [%1 + ll_next]
%endm
_dll_seek_backward:
mov rax, [rax + dll_prev]
ret
_dll_seek_forward:
mov rax, [rax + dll_next]
ret
%macro dll_seek 0-2 rax,"forward"
%if "%1" != "%rax"
mov rax, %1
%endif
%if %2 == "forward"
call _dll_seek_forward
%elif %2 == "backward"
call _dll_seek_backward
%else
%error "Direction not specified!"
%endif
%endm
_dll_end:
.loop:
mov rcx, [rax + dll_next]
cmp rcx, 0
je .end
call _dll_seek_forward
jmp .loop
.end:
ret
%macro dll_end 0-1 rax
%if "%1" != "rax"
mov rax, %1
%endif
call _dll_end
%endm
%macro ll_push 2
;; %1 = Current Linked List Node
;; %2 = Value to push (Must fit in a register, larger must be pushed as pointer to the underlying structure)
lln_alloc
mov qword [%1 + ll_next], rax
mov qword [rax + ll_value], %2
%endm
%macro dll_push 2
;; %1 = Current Doubly Linked List Node
;; %2 = Value to push (Must fit in a register, larger must be pushed as pointer to the underlying structure)
dll_alloc
mov rcx, [%1 + dll_next]
cmp rcx, 0
je %%skip
mov qword [rcx + dll_prev], rax
%%skip:
mov qword [%1 + dll_next], rax
mov qword [rax + dll_next], rcx
mov qword [rax + dll_value], %2
mov qword [rax + dll_prev], %1
%endm
_dll_free:
push rbp
mov rbp, rsp
push rbx
dll_end
.free_loop:
mov rbx, [rax + dll_prev]
dll_free
mov rax, rbx
cmp rbx, 0
jne .free_loop
pop rbx
mov rsp, rbp
pop rbp
ret
%endif
|