%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