NASM - The Netwide Assembler
NASM Forum => Example Code => Topic started by: encryptor256 on November 15, 2013, 11:11:15 AM
-
Hello!
* It also support's sublists.
Information:
; ---------------------------------------------------------------- ;
; This is: Win64 Linked List (NODELIST) NASM, GOLINK.
; Author: J.K. Encryptor256.
; Date: November 15, 2013.
; ---------------------------------------------------------------- ;
; Description:
;
; This is my recent version of Linked List's, named NODELIST.
; It's actually pretty easy.
; ---------------------------------------------------------------- ;
; Using:
;
; 1. Compiler:
; 1.1. NASM (The Netwide Assembler)
; 1.2. Web:(http://nasm.us/)
;
; 2. Linker:
; 2.1. GoLink (Jeremy Gordon's Go Tools for Win32 and Win64)
; 2.2. Web:(http://www.godevtool.com/)
;
; 3. Editor:
; 3.1. PSPad (Freeware Editor)
; 3.2. Web:(http://www.pspad.com/en/)
;
; ---------------------------------------------------------------- ;
; How to compile and link,
;
; Easy, in the way, i did:
;
; 1. NASM: "nasm.exe -f win64 main.asm -o main.obj"
; Produces => main.obj: 5.66 KB (5,802 bytes)
;
; 2. GoLink: "golink.exe /entry main /console main.obj MSVCRT.dll"
; Produces => main.exe: 4.00 KB (4,096 bytes)
;
; ---------------------------------------------------------------- ;
; Linked list, named: NODELIST
; Linked list, node named: NODELISTNODE
; Procedures:
; 1. nodeListAdd
; 2. nodeListNodeNew
; 3. nodeListNew
; 4. nodeListPrint
; 5. nodeListCursorSet
; 6. nodeListCursorNext
; 7. nodeListCursorData
; 8. nodeListNodeDelete
; 9. nodeListDelete
; ---------------------------------------------------------------- ;
Data: These are structure offsets.
; ------------------------------------------- ;
; NODELIST Variables ;
; ------------------------------------------- ;
; NODELIST ;
NODELIST.FIRST equ (8*0) ;
NODELIST.LAST equ (8*1) ;
NODELIST.COUNT equ (8*2) ;
NODELIST_SIZE equ (8*3) ;
; ------------------------------------------- ;
; NODELISTNODE ;
NODELISTNODE.PARENT equ (8*0) ;
NODELISTNODE.PREV equ (8*1) ;
NODELISTNODE.TYPE equ (8*2) ;
NODELISTNODE.DATA equ (8*3) ;
NODELISTNODE.NEXT equ (8*4) ;
NODELISTNODE_SIZE equ (8*5) ;
; ------------------------------------------- ;
; NODELISTNODE list indicator ;
NODELISTNODE_TYPE_LIST equ (0xFFFF) ;
; ------------------------------------------- ;
Procedures: What kind'a procedures im using?
1. Ordinary: add, delete, ... procedures.
2. Extra: cursor procedures.
; ########################################### ;
; nodeListAdd: Procedure
;
; Usage:
; mov rcx,qword addrOfNodeList
; mov rdx,qword (nodeType)
; mov r8,qword (data)
; call nodeListNodeNew
;
; Returns nothing.
; Set's carry flag on error.
; Clear's carry flag on success.
;
; ########################################### ;
; nodeListNodeNew: Procedure
;
; Usage:
; call nodeListNodeNew
;
; Takes no arguments.
; Returns pointer to NODELISTNODE structure (RAX).
; Set's carry flag on error.
; Clear's carry flag on success.
;
; ########################################### ;
; nodeListNew: Procedure
;
; Usage:
; call nodeListNew
;
; Takes no arguments.
; Returns pointer to NODELIST structure (RAX).
; Set's carry flag on error.
; Clear's carry flag on success.
;
; ########################################### ;
; nodeListPrint: Procedure
;
; Usage:
; mov rcx,qword nodeListAddress
; call nodeListPrint
;
; Returns nothing.
; Set's carry flag on error.
; Clear's carry flag on success.
;
; ########################################### ;
; nodeListCursorSet: Procedure
;
; Uses: RCX, RBX
;
; Usage:
; mov rcx,qword nodeListAddress
; call nodeListCursorSet
;
; Returns nothing.
; Set's carry flag on error.
; Clear's carry flag on success.
; OnSuccess: Will store list.first into RBX.
;
; ########################################### ;
; nodeListCursorNext: Procedure
;
; Uses: RBX
;
; Usage:
; call nodeListCursorSet
;
; Returns nothing.
; Set's carry flag on error.
; Clear's carry flag on success.
; OnSuccess: Will store node.next into RBX.
;
; ########################################### ;
; nodeListCursorData: Procedure
;
; Uses: RBX, RAX, RCX
;
; Usage:
; call nodeListCursorData
;
; Returns nothing.
; Set's carry flag on error.
; Clear's carry flag on success.
; OnSuccess:
; Will get data from node(RBX).
; Will set node.type into RCX.
; Will set node.data into RAX.
;
; ########################################### ;
; nodeListNodeDelete: Procedure
;
; Usage:
; mov rcx,qword addrOfNodeListNode
; mov rdx,qword addrOfDeleteHandler
; call nodeListNodeDelete
;
; deleteHandler:
; ; rcx - node.type
; ; rdx - node.data
; ; If data is a pointer to buffer,
; ; that, could be deleted, by,
; ; providing a deletehandler to this
; ; procedure.
; ret
;
; Returns nothing.
; Set's carry flag on error.
; Clear's carry flag on success.
;
; ########################################### ;
; nodeListDelete: Procedure
;
; Usage:
; mov rcx,qword addrOfNodeList
; mov rdx,qword addrOfDeleteHandler
; call nodeListDelete
;
; deleteHandler:
; ; rcx - node.type
; ; rdx - node.data
; ; If data is a pointer to buffer,
; ; that, could be deleted, by,
; ; providing a deletehandler to this
; ; procedure.
; ret
;
; Returns deleted node count into RAX.
; Set's carry flag on error.
; Clear's carry flag on success.
;
; ########################################### ;
nodeListNodeDelete: This is the most longest, in bytes.
nodeListNodeDelete:
; Check argument - rcx:
cmp rcx,qword (0) ; For zero
je .earlyQuit
cmp qword [rcx+NODELISTNODE.PARENT],qword (0) ; For parent
je .earlyQuit
mov rax,qword [rcx+NODELISTNODE.PARENT] ; Check parent count > 0
cmp qword [rax+NODELIST.COUNT],qword (0)
jg .haveValidArgs
.earlyQuit:
stc
ret
.haveValidArgs:
; Save arguments:
mov qword [rsp+8*1],rcx; address of node list node
mov qword [rsp+8*2],rdx; address of delete handler
; mov qword [rsp+8*3],r8; (unused register)
; mov qword [rsp+8*4],r9; (unused register)
; ! (Note1) RBX, at first, is used as a, counter,
; of node's deleted.
; ! (Note2) RBX, also, is used to determine
; existence of node.prev's, node.next's.
; Create stack
push rbp
mov rbp,rsp
push rbx
lea rsp,[rsp-(8*5)]
; Init RBX counter (ref. Note1)
xor rbx,rbx
.check1:
; Check 1: If node.type is list, call => nodeListDelete
cmp qword [rcx+NODELISTNODE.TYPE],qword (NODELISTNODE_TYPE_LIST)
jl .check2
; rdx remains set
mov rcx,qword [rcx+NODELISTNODE.DATA]
call nodeListDelete
mov rbx,rax ; (ref. Note1)
jnc .checkDone
jmp .quit
.check2:
; Check 2: Pass node.type and node.data to delete handler
cmp rdx,qword (0)
je .checkDone
mov rax,rdx
mov rdx,qword [rcx+NODELISTNODE.DATA]
mov rcx,qword [rcx+NODELISTNODE.TYPE]
call rax
.checkDone:
mov rcx,qword [rsp+8*5+8*2+8*1]; Assign node to RCX
mov rdx,qword [rcx+NODELISTNODE.PARENT]; Assign node.parent to RDX
; Save RBX into RAX (ref. Note1)
mov rax,rbx
; Determine if node have prev or next (ref. Note2)
xor rbx,rbx
cmp qword [rcx+NODELISTNODE.PREV],qword (0)
je .prevChecked
inc rbx
.prevChecked:
cmp qword [rcx+NODELISTNODE.NEXT],qword (0)
je .nextChecked
inc rbx
inc rbx
.nextChecked:
; Operate by rbx
.rbxIs0:
cmp rbx,qword (0)
jne .rbxIs1
; node is the only one
mov qword [rdx+NODELIST.FIRST],qword (0)
mov qword [rdx+NODELIST.LAST],qword (0)
jmp .rbxIsDone
.rbxIs1:
cmp rbx,qword (1)
jne .rbxIs2
; node is last
mov r8,qword [rcx+NODELISTNODE.PREV]
mov qword [r8+NODELISTNODE.NEXT],qword (0)
mov qword [rdx+NODELIST.LAST],r8
jmp .rbxIsDone
.rbxIs2:
cmp rbx,qword (2)
jne .rbxIs3
; node is first
mov r8,qword [rcx+NODELISTNODE.NEXT]
mov qword [r8+NODELISTNODE.PREV],qword (0)
mov qword [rdx+NODELIST.FIRST],r8
jmp .rbxIsDone
.rbxIs3:
; node is in the middle
mov r8,qword [rcx+NODELISTNODE.PREV]
mov r9,qword [rcx+NODELISTNODE.NEXT]
mov qword [r8+NODELISTNODE.NEXT],r9
mov qword [r9+NODELISTNODE.PREV],r8
.rbxIsDone:
; Restore RBX into RAX (ref. Note1)
mov rbx,rax
inc rbx
; Decrease list.count
dec qword [rdx+NODELIST.COUNT]
; Release node memory
; rcx is already set
call free
; Set success
mov rax,rbx
clc
; Deallocate stack n quit
.quit:
lea rsp,[rsp+(8*5)]
pop rbx
pop rbp
ret
How to use:
; ---------------------------------------------------------------- ;
; Example code info:
; 1. Create list, nr.1.
; 2. Add four items to list, nr.1.
; 3. Create list, nr.2.
; 4. Add list, nr.2., to list, nr.1.
; 5. Print list, nr.1.
; 6. Delete list, nr.1.
; -. Uses deleteHandler when deleting list's.
; -. Data n Type, can be accessed via deletionHandler,
; -. during deletion procedure.
; -. Uses createList procedure to create list, nr.2.
; ---------------------------------------------------------------- ;
; MAIN (Custom Procedure)
main:
push rbp
mov rbp,rsp
push rbx
lea rsp,[rsp-(8*15)]
; Create new list, nr. 1.
call nodeListNew
jc .quit
; Save list, nr. 1., address
mov qword [rsp+8*10],rax
; Add node to list, nr. 1.
mov rcx,qword [rsp+8*10]
mov rdx,qword 12
mov r8,qword 14
call nodeListAdd
jc .quit
; Add node to list, nr. 1.
mov rcx,qword [rsp+8*10]
mov rdx,qword 13
mov r8,qword 15
call nodeListAdd
jc .quit
; Add node to list, nr. 1.
mov rcx,qword [rsp+8*10]
mov rdx,qword 14
mov r8,qword 16
call nodeListAdd
jc .quit
; Add node to list, nr. 1.
mov rcx,qword [rsp+8*10]
mov rdx,qword 15
mov r8,qword 17
call nodeListAdd
jc .quit
; Create new list, nr. 2.
mov rcx,qword 10
mov rdx,qword 100
mov r8,qword 10
call createList
; Save list, nr. 2., address
mov qword [rsp+8*11],rax
; Add list, nr. 2, to list, nr. 1.
mov rcx,qword [rsp+8*10]
mov rdx,qword (NODELISTNODE_TYPE_LIST+1)
mov r8,qword [rsp+8*11]
call nodeListAdd
jc .quit
; Print list, nr. 1.
mov rcx,qword [rsp+8*10]
call nodeListPrint
jc .quit
; Delete list, nr. 1.
mov rcx,qword [rsp+8*10]
mov rdx,qword deleteHandler
call nodeListDelete
jc .quit
.quit:
lea rsp,[rsp+(8*15)]
pop rbx
pop rbp
ret
Output: (First list's, last item is another list)
[NODELIST:0x3EBE90]
--> 0. Type: 12, Data: 14 <--
--> 1. Type: 13, Data: 15 <--
--> 2. Type: 14, Data: 16 <--
--> 3. Type: 15, Data: 17 <--
--> 4. Type: NODELIST, Data: 0x3EBEB0 <--
[NODELIST:0x3EBEB0]
--> 0. Type: 10, Data: 100 <--
--> 1. Type: 11, Data: 100 <--
--> 2. Type: 12, Data: 100 <--
--> 3. Type: 13, Data: 100 <--
--> 4. Type: 14, Data: 100 <--
--> 5. Type: 15, Data: 100 <--
--> 6. Type: 16, Data: 100 <--
--> 7. Type: 17, Data: 100 <--
--> 8. Type: 18, Data: 100 <--
--> 9. Type: 19, Data: 100 <--
[/NODELIST:0x3EBEB0]
[/NODELIST:0x3EBE90]
DeleteHandler: Type: 12, Data: 14
DeleteHandler: Type: 13, Data: 15
DeleteHandler: Type: 14, Data: 16
DeleteHandler: Type: 15, Data: 17
DeleteHandler: Type: 10, Data: 100
DeleteHandler: Type: 11, Data: 100
DeleteHandler: Type: 12, Data: 100
DeleteHandler: Type: 13, Data: 100
DeleteHandler: Type: 14, Data: 100
DeleteHandler: Type: 15, Data: 100
DeleteHandler: Type: 16, Data: 100
DeleteHandler: Type: 17, Data: 100
DeleteHandler: Type: 18, Data: 100
DeleteHandler: Type: 19, Data: 100
Video:
Watch source code and runtime video on youtube, named: "Win64 Linked List NODELIST NASM GOLINK".
Link: http://youtu.be/cGZ2WJljJSY (http://youtu.be/cGZ2WJljJSY)
Attachment:
Added attachment, named: "main.zip", which includes source code.
And that's it!
Encryptor256!!!
-
Hello!
Today i created a better one.
Data structures are just like in C++ OOP with inheritance. :)
nodebase is inherited by nodedata and nodelist.
This is how you do it, in NASM:
* The key to understand it, is to look at offsets.
; -----------------------------------------------------------;
; node n nodelist, data structure offsets n constants
; node base
nodebase.parent equ (8*0)
nodebase.type equ (8*1)
nodebase.prev equ (8*2)
nodebase.next equ (8*3)
; node data:
nodedata.data equ (8*4)
nodedata_size equ (8*5)
; node list:
nodelist.first equ (8*4)
nodelist.last equ (8*5)
nodelist.count equ (8*6)
nodelist_size equ (8*7)
node_type_list equ (0xFFFF)
Procedures, found in source code:
- nodelist.print
- nodelist.getList
- deletehandler
- main
- nodedata.new
- nodelist.new
- nodelist.add.nodebase
- sysAllocateMemory
- nodelist.cursor.set.on.first
- nodelist.cursor.set.on.last
- nodelist.cursor.next
- nodelist.cursor.prev
- nodebase.remove
- nodebase.delete
This is source code output, pretty interesting:
[[[ --- FIRST --- ]]]
* Create list A.
* Print list A.
[nodelist addr: 4770624, type: 65535]
[node] type: 10, data: 20 [/node]
[node] type: 11, data: 21 [/node]
[node] type: 12, data: 22 [/node]
[node] type: 13, data: 23 [/node]
[node] type: 14, data: 24 [/node]
[node] type: 15, data: 25 [/node]
[node] type: 16, data: 26 [/node]
[node] type: 17, data: 27 [/node]
[node] type: 18, data: 28 [/node]
[node] type: 19, data: 29 [/node]
[/nodelist addr: 4770624, type: 65535]
[[[ --- SECOND --- ]]]
* Create list B.
* Add list B. to list A.
* Print list A.
[nodelist addr: 4770624, type: 65535]
[node] type: 10, data: 20 [/node]
[node] type: 11, data: 21 [/node]
[node] type: 12, data: 22 [/node]
[node] type: 13, data: 23 [/node]
[node] type: 14, data: 24 [/node]
[node] type: 15, data: 25 [/node]
[node] type: 16, data: 26 [/node]
[node] type: 17, data: 27 [/node]
[node] type: 18, data: 28 [/node]
[node] type: 19, data: 29 [/node]
[nodelist addr: 4770688, type: 65536]
[node] type: 55, data: 80 [/node]
[node] type: 56, data: 81 [/node]
[node] type: 57, data: 82 [/node]
[node] type: 58, data: 83 [/node]
[node] type: 59, data: 84 [/node]
[node] type: 60, data: 85 [/node]
[node] type: 61, data: 86 [/node]
[node] type: 62, data: 87 [/node]
[node] type: 63, data: 88 [/node]
[node] type: 64, data: 89 [/node]
[/nodelist addr: 4770688, type: 65536]
[/nodelist addr: 4770624, type: 65535]
[[[ --- THIRD --- ]]]
* Delete list A.
<deleteHandler> type: 10, data: 20 </deleteHandler>
<deleteHandler> type: 11, data: 21 </deleteHandler>
<deleteHandler> type: 12, data: 22 </deleteHandler>
<deleteHandler> type: 13, data: 23 </deleteHandler>
<deleteHandler> type: 14, data: 24 </deleteHandler>
<deleteHandler> type: 15, data: 25 </deleteHandler>
<deleteHandler> type: 16, data: 26 </deleteHandler>
<deleteHandler> type: 17, data: 27 </deleteHandler>
<deleteHandler> type: 18, data: 28 </deleteHandler>
<deleteHandler> type: 19, data: 29 </deleteHandler>
<deleteHandler> type: 55, data: 80 </deleteHandler>
<deleteHandler> type: 56, data: 81 </deleteHandler>
<deleteHandler> type: 57, data: 82 </deleteHandler>
<deleteHandler> type: 58, data: 83 </deleteHandler>
<deleteHandler> type: 59, data: 84 </deleteHandler>
<deleteHandler> type: 60, data: 85 </deleteHandler>
<deleteHandler> type: 61, data: 86 </deleteHandler>
<deleteHandler> type: 62, data: 87 </deleteHandler>
<deleteHandler> type: 63, data: 88 </deleteHandler>
<deleteHandler> type: 64, data: 89 </deleteHandler>
Process completed, Exit Code 20.
Execution time: 00:00.156
Exit Code 20, means it has deleted 20 nodes, actually it released 20 nodes and 2x lists, lists are excluded, because they are containers, not a direct meaning of a node.
When deleting a list, i pass, a deleteHandler, so, when node is being deleted, then its type and data are sent to deleteHandler. This is useful if that node data is a pointer and must be freed by the user.
Attachment:
I create a project with:
; 3.1. PSPad (Freeware Editor)
; 3.2. Web:(http://www.pspad.com/en/)
Added an attachment, named: "pspad_project_linkedlist.zip", which includes all project files, possibility to replicate the "output" mentioned above.
* If you know how these linked list data structures work, you can easely build a torrent file, bencoded string parser.
Bye,
Encryptor!!!
-
Hello!
Today i updated to new one, even better, smarter, clever one.
New:
- Data structure nodelistex
- Traverse tree by query procedure (handler required)
- Two procedures - nodelistex.new, nodelistex.query
- All procedures are now aligned to 16 byte boundaries
- Replaced all "register compare against zero" with test instruction
- All procedures experienced at least some changes
Query handler procedure is programmable.
Full description about procedures can be found in source code "inc" files.
Using PsPad code editor, mentioned at prev post.
Data structures:
; nodelist:
; -----------------------------------------------------------;
; node (base node)
node.parent equ (8*0)
node.type equ (8*1)
node.prev equ (8*2)
node.next equ (8*3)
; node data: inherits node
nodedata.data equ (8*4)
nodedata_size equ (8*5)
; node list: inherits node
nodelist.first equ (8*4)
nodelist.last equ (8*5)
nodelist.count equ (8*6)
nodelist_size equ (8*7)
; node list ex: inherits nodelist
nodelistex.deletehandler equ (8*7)
nodelistex.queryhandler equ (8*8)
nodelistex_size equ (8*9)
; node list indicator:
; If node type is greater or equal than,
; node list idicator, then, node is,
; cosidered to be a node with,
; nodelist base structure.
node_type_list equ (0x0FFFFF)
; node list ex indicator:
; If node type is greater or equal than,
; node listex idicator, then, node is,
; cosidered to be a node with,
; nodelistex base structure.
node_type_listex equ (0x1FFFFF)
; node data indicator:
; If node type is equal to
; node data idicator, then, node is,
; cosidered to be a node with,
; nodedata base structure.
node_type_data equ (0x010000)
Current procedures:
global node.new,\
nodelist.add.node, nodelist.add.nodedata,\
nodelist.cursor.set.on.first, nodelist.cursor.set.on.last,\
nodelist.cursor.next, nodelist.cursor.prev,\
node.remove, node.delete,\
nodelistex.new, nodelistex.query
These two are completely new:
; -----------------------------------------------------------;
;
; Procedure: nodelistex.new
;
; Create's new a nodelistex.
; RCX - delete handler address.
; RDX - get handler address.
;
; Usage:
;
; ; Create nodelistex node
; mov rcx,qword delHandlerAddress
; mov rdx,qword getHandlerAddress
; call nodelistex.new
; jc .quitError
;
; Returns a pointer to node into RAX.
; Set's carry flag on error.
; Clear's carry flag on success.
;
; -----------------------------------------------------------;
;
; Procedure: nodelistex.query
;
; RCX - nodelistex address
; RDX - data1
; R8 - data2
; R9 - data3
;
; Usage:
;
; ; Create new list
; mov rcx,deletehandler
; mov rdx,queryhandler
; call nodelistex.new
; jc .quit
;
; mov rcx,rax
; xor rdx,rdx
; xor r8,r8
; xor r9,r9
; call nodelistex.query
; jc .noData
;
; Returns value by
; Procedure: queryhandler.
; Set's carry flag on error.
; Clear's carry flag on success.
;
; -----------------------------------------------------------;
Query procedure:
; -----------------------------------------------------------;
;
; Procedure: queryhandler (User Defined)
;
; RCX - node
; RDX - data (If modify, use R12)
; R8 - data (If modify, use R13)
; R9 - data (If modify, use R14)
;
; Caller has provided with three volatile registers: R12-14.
; Modify them, will modify incoming arguments RDX, R8, R9.
;
; This procedure will return result for nodelistex.query.
;
; ! Set carry flag to continue query further:
; If node is list type,
; then, returned RAX indicates, what node to pick next:
; 0 -> first
; 1 -> last
; 2 -> next
; 4 -> prev
; 8 -> parent
; If node is non-list type,
; then, returned RAX indicates, what node to pick next:
; 0 -> next
; 1 -> prev
; 2 -> parent
;
; ! Clear carry flag to stop query further:
; Returns result in RAX on success.
; On success, register values are set:
; 1. RCX - nodelistex address (remains set)
; 2. RDX - R12 (changed or unchanged data)
; 3. R8 - R13 (changed or unchanged data)
; 4. R9 - R14 (changed or unchanged data)
;
; EXAMPLE:
; Traverse list from bottom and print
; node address and modified arguments.
;
; ...
; txt_text: db 10,".query. %d %d %d %d",0
; ...
;
;
; align 16
; queryhandler:
;
; ; Save args
; mov qword [rsp+8*1],rcx;
; mov qword [rsp+8*2],rdx;
; mov qword [rsp+8*3],r8;
; mov qword [rsp+8*4],r9;
;
; ; Create stack
; push rbp
; mov rbp,rsp
; push rbx
; lea rsp,[rsp-(8*5)]
;
; mov qword [rsp+8*4],r9
; mov r9,r8
; mov r8,rdx
; mov rdx,rcx
; mov rcx,qword txt_text
; call printf
;
; inc r12
; mov r13,10
; inc r14
;
; xor rax,rax
; mov rax,1
; stc
; .quit:
; ; Clear stack n quit
; lea rsp,[rsp+(8*5)]
; pop rbx
; pop rbp
; ret
;
; ...
; txt_format_dhandler: db 10,"<deleteHandler> type: %d, data: %d </deleteHandler>",0
; ...
; align 16
; deletehandler:
; lea rsp,[rsp-8*5]
;
; mov r9,qword [rcx+nodedata.data]
; mov r8,qword [rcx+node.type]
; mov rdx,qword txt_format_dhandler
; mov rcx,qword buffer
; call sprintf
; mov rcx,qword buffer
; call printf
;
; lea rsp,[rsp+8*5]
; ret
;
; -----------------------------------------------------------;
Source code output:
[code begin]
; Create main list
[nodelist addr: 4107856, type: 2097151]
[node addr: 4114064, type: 65536, parent: 4107856] data: 10 [/node]
[node addr: 4114112, type: 65536, parent: 4107856] data: 11 [/node]
[node addr: 4114160, type: 65536, parent: 4107856] data: 12 [/node]
[node addr: 4114208, type: 65536, parent: 4107856] data: 13 [/node]
[node addr: 4114256, type: 65536, parent: 4107856] data: 14 [/node]
[node addr: 4114304, type: 65536, parent: 4107856] data: 15 [/node]
[node addr: 4114352, type: 65536, parent: 4107856] data: 16 [/node]
[node addr: 4114400, type: 65536, parent: 4107856] data: 17 [/node]
[node addr: 4114448, type: 65536, parent: 4107856] data: 18 [/node]
[node addr: 4114496, type: 65536, parent: 4107856] data: 19 [/node]
[/nodelist addr: 4107856, type: 2097151]
; Create secondary list
[nodelist addr: 4107936, type: 2097151]
[node addr: 4114544, type: 65536, parent: 4107936] data: 20 [/node]
[node addr: 4114592, type: 65536, parent: 4107936] data: 21 [/node]
[node addr: 4114640, type: 65536, parent: 4107936] data: 22 [/node]
[node addr: 4114688, type: 65536, parent: 4107936] data: 23 [/node]
[node addr: 4114736, type: 65536, parent: 4107936] data: 24 [/node]
[node addr: 4114784, type: 65536, parent: 4107936] data: 25 [/node]
[node addr: 4114832, type: 65536, parent: 4107936] data: 26 [/node]
[node addr: 4114880, type: 65536, parent: 4107936] data: 27 [/node]
[node addr: 4114928, type: 65536, parent: 4107936] data: 28 [/node]
[node addr: 4114976, type: 65536, parent: 4107936] data: 29 [/node]
[/nodelist addr: 4107936, type: 2097151]
; Add secondary list to main list
[nodelist addr: 4107856, type: 2097151]
[node addr: 4114064, type: 65536, parent: 4107856] data: 10 [/node]
[node addr: 4114112, type: 65536, parent: 4107856] data: 11 [/node]
[node addr: 4114160, type: 65536, parent: 4107856] data: 12 [/node]
[node addr: 4114208, type: 65536, parent: 4107856] data: 13 [/node]
[node addr: 4114256, type: 65536, parent: 4107856] data: 14 [/node]
[node addr: 4114304, type: 65536, parent: 4107856] data: 15 [/node]
[node addr: 4114352, type: 65536, parent: 4107856] data: 16 [/node]
[node addr: 4114400, type: 65536, parent: 4107856] data: 17 [/node]
[node addr: 4114448, type: 65536, parent: 4107856] data: 18 [/node]
[node addr: 4114496, type: 65536, parent: 4107856] data: 19 [/node]
[nodelist addr: 4107936, type: 2097151]
[node addr: 4114544, type: 65536, parent: 4107936] data: 20 [/node]
[node addr: 4114592, type: 65536, parent: 4107936] data: 21 [/node]
[node addr: 4114640, type: 65536, parent: 4107936] data: 22 [/node]
[node addr: 4114688, type: 65536, parent: 4107936] data: 23 [/node]
[node addr: 4114736, type: 65536, parent: 4107936] data: 24 [/node]
[node addr: 4114784, type: 65536, parent: 4107936] data: 25 [/node]
[node addr: 4114832, type: 65536, parent: 4107936] data: 26 [/node]
[node addr: 4114880, type: 65536, parent: 4107936] data: 27 [/node]
[node addr: 4114928, type: 65536, parent: 4107936] data: 28 [/node]
[node addr: 4114976, type: 65536, parent: 4107936] data: 29 [/node]
[/nodelist addr: 4107936, type: 2097151]
[/nodelist addr: 4107856, type: 2097151]
; Create new empty list
[nodelist addr: 4108016, type: 2097151]
[/nodelist addr: 4108016, type: 2097151]
; Add empty list to main list
[nodelist addr: 4107856, type: 2097151]
[node addr: 4114064, type: 65536, parent: 4107856] data: 10 [/node]
[node addr: 4114112, type: 65536, parent: 4107856] data: 11 [/node]
[node addr: 4114160, type: 65536, parent: 4107856] data: 12 [/node]
[node addr: 4114208, type: 65536, parent: 4107856] data: 13 [/node]
[node addr: 4114256, type: 65536, parent: 4107856] data: 14 [/node]
[node addr: 4114304, type: 65536, parent: 4107856] data: 15 [/node]
[node addr: 4114352, type: 65536, parent: 4107856] data: 16 [/node]
[node addr: 4114400, type: 65536, parent: 4107856] data: 17 [/node]
[node addr: 4114448, type: 65536, parent: 4107856] data: 18 [/node]
[node addr: 4114496, type: 65536, parent: 4107856] data: 19 [/node]
[nodelist addr: 4107936, type: 2097151]
[node addr: 4114544, type: 65536, parent: 4107936] data: 20 [/node]
[node addr: 4114592, type: 65536, parent: 4107936] data: 21 [/node]
[node addr: 4114640, type: 65536, parent: 4107936] data: 22 [/node]
[node addr: 4114688, type: 65536, parent: 4107936] data: 23 [/node]
[node addr: 4114736, type: 65536, parent: 4107936] data: 24 [/node]
[node addr: 4114784, type: 65536, parent: 4107936] data: 25 [/node]
[node addr: 4114832, type: 65536, parent: 4107936] data: 26 [/node]
[node addr: 4114880, type: 65536, parent: 4107936] data: 27 [/node]
[node addr: 4114928, type: 65536, parent: 4107936] data: 28 [/node]
[node addr: 4114976, type: 65536, parent: 4107936] data: 29 [/node]
[/nodelist addr: 4107936, type: 2097151]
[nodelist addr: 4108016, type: 2097151]
[/nodelist addr: 4108016, type: 2097151]
[/nodelist addr: 4107856, type: 2097151]
; Create new data node
; Add data node to main list
; Print main list
[nodelist addr: 4107856, type: 2097151]
[node addr: 4114064, type: 65536, parent: 4107856] data: 10 [/node]
[node addr: 4114112, type: 65536, parent: 4107856] data: 11 [/node]
[node addr: 4114160, type: 65536, parent: 4107856] data: 12 [/node]
[node addr: 4114208, type: 65536, parent: 4107856] data: 13 [/node]
[node addr: 4114256, type: 65536, parent: 4107856] data: 14 [/node]
[node addr: 4114304, type: 65536, parent: 4107856] data: 15 [/node]
[node addr: 4114352, type: 65536, parent: 4107856] data: 16 [/node]
[node addr: 4114400, type: 65536, parent: 4107856] data: 17 [/node]
[node addr: 4114448, type: 65536, parent: 4107856] data: 18 [/node]
[node addr: 4114496, type: 65536, parent: 4107856] data: 19 [/node]
[nodelist addr: 4107936, type: 2097151]
[node addr: 4114544, type: 65536, parent: 4107936] data: 20 [/node]
[node addr: 4114592, type: 65536, parent: 4107936] data: 21 [/node]
[node addr: 4114640, type: 65536, parent: 4107936] data: 22 [/node]
[node addr: 4114688, type: 65536, parent: 4107936] data: 23 [/node]
[node addr: 4114736, type: 65536, parent: 4107936] data: 24 [/node]
[node addr: 4114784, type: 65536, parent: 4107936] data: 25 [/node]
[node addr: 4114832, type: 65536, parent: 4107936] data: 26 [/node]
[node addr: 4114880, type: 65536, parent: 4107936] data: 27 [/node]
[node addr: 4114928, type: 65536, parent: 4107936] data: 28 [/node]
[node addr: 4114976, type: 65536, parent: 4107936] data: 29 [/node]
[/nodelist addr: 4107936, type: 2097151]
[nodelist addr: 4108016, type: 2097151]
[/nodelist addr: 4108016, type: 2097151]
[node addr: 4115024, type: 65536, parent: 4107856] data: 27015 [/node]
[/nodelist addr: 4107856, type: 2097151]
; Basic query procedure example
.query. 4107856 0 0 0
.query. 4115024 1 10 1
.query. 4108016 2 10 2
.query. 4107936 3 10 3
.query. 4114976 4 10 4
.query. 4114928 5 10 5
.query. 4114880 6 10 6
.query. 4114832 7 10 7
.query. 4114784 8 10 8
.query. 4114736 9 10 9
.query. 4114688 10 10 10
.query. 4114640 11 10 11
.query. 4114592 12 10 12
.query. 4114544 13 10 13
.query. 4114496 14 10 14
.query. 4114448 15 10 15
.query. 4114400 16 10 16
.query. 4114352 17 10 17
.query. 4114304 18 10 18
.query. 4114256 19 10 19
.query. 4114208 20 10 20
.query. 4114160 21 10 21
.query. 4114112 22 10 22
.query. 4114064 23 10 23
; Delete main list
[deletingnode addr: 4114064, type: 65536] data: 10 [/deletingnode]
[deletingnode addr: 4114112, type: 65536] data: 11 [/deletingnode]
[deletingnode addr: 4114160, type: 65536] data: 12 [/deletingnode]
[deletingnode addr: 4114208, type: 65536] data: 13 [/deletingnode]
[deletingnode addr: 4114256, type: 65536] data: 14 [/deletingnode]
[deletingnode addr: 4114304, type: 65536] data: 15 [/deletingnode]
[deletingnode addr: 4114352, type: 65536] data: 16 [/deletingnode]
[deletingnode addr: 4114400, type: 65536] data: 17 [/deletingnode]
[deletingnode addr: 4114448, type: 65536] data: 18 [/deletingnode]
[deletingnode addr: 4114496, type: 65536] data: 19 [/deletingnode]
[deletingnode addr: 4114544, type: 65536] data: 20 [/deletingnode]
[deletingnode addr: 4114592, type: 65536] data: 21 [/deletingnode]
[deletingnode addr: 4114640, type: 65536] data: 22 [/deletingnode]
[deletingnode addr: 4114688, type: 65536] data: 23 [/deletingnode]
[deletingnode addr: 4114736, type: 65536] data: 24 [/deletingnode]
[deletingnode addr: 4114784, type: 65536] data: 25 [/deletingnode]
[deletingnode addr: 4114832, type: 65536] data: 26 [/deletingnode]
[deletingnode addr: 4114880, type: 65536] data: 27 [/deletingnode]
[deletingnode addr: 4114928, type: 65536] data: 28 [/deletingnode]
[deletingnode addr: 4114976, type: 65536] data: 29 [/deletingnode]
[deletingnode addr: 4115024, type: 65536] data: 27015 [/deletingnode]
[code end]
Process completed, Exit Code 0.
Execution time: 00:00.578
Pretty darn cool! :D
Added attachment: pspad_dds_sys.zip
- sys library, used by dds
- dds library
sys - system.
dds - dynamic data structures (linked list - node list).
dds project is example project which produced "source code output" above.
Bye, Encryptor256!!!
-
Hello!
This is not a joke. ;D
Today i updated dds - dynamic data structures library to a new version., again.
This version is better than previous ones.
What's new:
- All dds code is new, reworked sys library
- Some functions saves and restores all argument registers
Current procedures:
- node.new
- node.add
- node.remove
- node.delete
- node.query
- node.queryprocedure (used in example code)
- dbgPrintList (used in example code, print's a list, depth supportive)
- dbgCreateList (used in example code, creates new list: empty or with nodes)
+ sys library procedures:
- sysmemcheck
- sysmalloc
- sysfree
- sysHash
- sysbatohs ("sysByteArrayToHexString")
- sysrdfc ("sysReadFileContent")
Procedure description, example usage:
- for sys procedures consult file: sys.inc
- for dds procedures consult file: dds.inc
Current data structures:
; node - base node
node.parent equ (8*0)
node.type equ (8*1)
node.prev equ (8*2)
node.next equ (8*3)
; nodedata - data node inherits base node
nodedata.data equ (8*4)
nodedata_size equ (8*5)
; nodelist - list node inherits base node
nodelist.first equ (8*4)
nodelist.last equ (8*5)
nodelist.count equ (8*6)
nodelist_size equ (8*7)
; node data indicator
node_type_data equ (0x00FFFFFF)
; node list indicator
node_type_list equ (0x01000000)
; node with type value less equal than "node_type_data",
; is considered to be a data node.
; node with type value greater equal than "node_type_list",
; is considered to be a list node.
Example code, runtime test:
; ------------------------------------------------------------------------------
;
; -> PROCEDURE: main
;
; ------------------------------------------------------------------------------
align 16
main:
; Create stack
push rbp
mov rbp,rsp
push rbx
push r12
push r13
lea rsp,[rsp-(8*31)]
; Print info
mov rcx,qword txt_code_begin
call printf
; Create basic list A.
mov rcx,10
mov rdx,20
call dbgCreateList
jc .quit
; Save list A. address
mov qword [rsp+8*20],rax
; Print list A.
mov rcx,qword [rsp+8*20]
xor rdx,rdx
call dbgPrintList
jc .quit
; Query nodes from list A.
mov rcx,qword [rsp+8*20]
mov rdx,qword node.queryprocedure
xor r8,r8
xor r9,r9
call node.query
; Delete, list A., first node
mov rcx,qword [rsp+8*20]
mov rcx,qword [rcx+nodelist.first]
xor rdx,rdx
call node.delete
jc .quit
; Delete, list A., last node
mov rcx,qword [rsp+8*20]
mov rcx,qword [rcx+nodelist.last]
call node.delete
jc .quit
; Delete, list A., first->next->next node
mov rcx,qword [rsp+8*20]
mov rcx,qword [rcx+nodelist.first]
mov rcx,qword [rcx+node.next]
mov rcx,qword [rcx+node.next]
call node.delete
jc .quit
; Delete, list A., last->prev->prev node
mov rcx,qword [rsp+8*20]
mov rcx,qword [rcx+nodelist.last]
mov rcx,qword [rcx+node.prev]
mov rcx,qword [rcx+node.prev]
call node.delete
jc .quit
; Print list A.
mov rcx,qword [rsp+8*20]
xor rdx,rdx
call dbgPrintList
jc .quit
; Create basic list B.
mov rcx,15
mov rdx,400
call dbgCreateList
jc .quit
; Save list B. address
mov qword [rsp+8*21],rax
; Add list B. to list A.
mov rcx,qword [rsp+8*20]
mov rdx,qword [rsp+8*21]
xor r8,r8
call node.add
jc .quit
; Create empty list C.
mov rcx,0
mov rdx,0
call dbgCreateList
jc .quit
; Save list C. address
mov qword [rsp+8*22],rax
; Add list C. to list B.
mov rcx,qword [rsp+8*21]
mov rdx,qword [rsp+8*22]
xor r8,r8
call node.add
jc .quit
; Print list A.
mov rcx,qword [rsp+8*20]
xor rdx,rdx
call dbgPrintList
jc .quit
; Delete list A.
mov rcx,qword [rsp+8*20]
xor rdx,rdx
call node.delete
jc .quit
; Print info
mov rcx,qword txt_code_end
call printf
call sysmemcheck
.quit:
; Clear stack n quit
lea rsp,[rsp+(8*31)]
pop r13
pop r12
pop rbx
pop rbp
ret
Commentary output (commentary_output.txt):
[code begin]
; Create basic list A.
; Print list A.
[nodelist address: 4107856, type: 16777216, first: 4770624, last: 4771200, count: 10]
[nodedata address: 4770624, type: 16777215, data: 20]
[nodedata address: 4770688, type: 16777215, data: 21]
[nodedata address: 4770752, type: 16777215, data: 22]
[nodedata address: 4770816, type: 16777215, data: 23]
[nodedata address: 4770880, type: 16777215, data: 24]
[nodedata address: 4770944, type: 16777215, data: 25]
[nodedata address: 4771008, type: 16777215, data: 26]
[nodedata address: 4771072, type: 16777215, data: 27]
[nodedata address: 4771136, type: 16777215, data: 28]
[nodedata address: 4771200, type: 16777215, data: 29]
[/nodelist]
; Query nodes from list A.
; Query for nodedata nodes, that (nodedata.data % 3)==0
[query node that (nodedata.data % 3)==0 ] node address 4770688 [/query node]
[query node that (nodedata.data % 3)==0 ] node address 4770880 [/query node]
[query node that (nodedata.data % 3)==0 ] node address 4771072 [/query node]
; Delete, list A., first node
; Delete, list A., last node
; Delete, list A., first->next->next node
; Delete, list A., last->prev->prev node
; Print list A.
[nodelist address: 4107856, type: 16777216, first: 4770688, last: 4771136, count: 6]
[nodedata address: 4770688, type: 16777215, data: 21]
[nodedata address: 4770752, type: 16777215, data: 22]
[nodedata address: 4770880, type: 16777215, data: 24]
[nodedata address: 4770944, type: 16777215, data: 25]
[nodedata address: 4771072, type: 16777215, data: 27]
[nodedata address: 4771136, type: 16777215, data: 28]
[/nodelist]
; Create basic list B.
; Add list B. to list A.
; Create empty list C.
; Add list C. to list B.
; Print list A.
[nodelist address: 4107856, type: 16777216, first: 4770688, last: 4107936, count: 7]
[nodedata address: 4770688, type: 16777215, data: 21]
[nodedata address: 4770752, type: 16777215, data: 22]
[nodedata address: 4770880, type: 16777215, data: 24]
[nodedata address: 4770944, type: 16777215, data: 25]
[nodedata address: 4771072, type: 16777215, data: 27]
[nodedata address: 4771136, type: 16777215, data: 28]
[nodelist address: 4107936, type: 16777216, first: 4771008, last: 4108016, count: 16]
[nodedata address: 4771008, type: 16777215, data: 400]
[nodedata address: 4770816, type: 16777215, data: 401]
[nodedata address: 4771200, type: 16777215, data: 402]
[nodedata address: 4770624, type: 16777215, data: 403]
[nodedata address: 4771264, type: 16777215, data: 404]
[nodedata address: 4771328, type: 16777215, data: 405]
[nodedata address: 4771392, type: 16777215, data: 406]
[nodedata address: 4771456, type: 16777215, data: 407]
[nodedata address: 4771520, type: 16777215, data: 408]
[nodedata address: 4771584, type: 16777215, data: 409]
[nodedata address: 4771648, type: 16777215, data: 410]
[nodedata address: 4771712, type: 16777215, data: 411]
[nodedata address: 4771776, type: 16777215, data: 412]
[nodedata address: 4771840, type: 16777215, data: 413]
[nodedata address: 4771904, type: 16777215, data: 414]
[nodelist address: 4108016, type: 16777216, first: 0, last: 0, count: 0]
[/nodelist]
[/nodelist]
[/nodelist]
; Delete list A.
[node being deleted] node address 4107856 [/node being deleted]
[node being deleted] node address 4770688 [/node being deleted]
[node being deleted] node address 4770752 [/node being deleted]
[node being deleted] node address 4770880 [/node being deleted]
[node being deleted] node address 4770944 [/node being deleted]
[node being deleted] node address 4771072 [/node being deleted]
[node being deleted] node address 4771136 [/node being deleted]
[node being deleted] node address 4107936 [/node being deleted]
[node being deleted] node address 4771008 [/node being deleted]
[node being deleted] node address 4770816 [/node being deleted]
[node being deleted] node address 4771200 [/node being deleted]
[node being deleted] node address 4770624 [/node being deleted]
[node being deleted] node address 4771264 [/node being deleted]
[node being deleted] node address 4771328 [/node being deleted]
[node being deleted] node address 4771392 [/node being deleted]
[node being deleted] node address 4771456 [/node being deleted]
[node being deleted] node address 4771520 [/node being deleted]
[node being deleted] node address 4771584 [/node being deleted]
[node being deleted] node address 4771648 [/node being deleted]
[node being deleted] node address 4771712 [/node being deleted]
[node being deleted] node address 4771776 [/node being deleted]
[node being deleted] node address 4771840 [/node being deleted]
[node being deleted] node address 4771904 [/node being deleted]
[node being deleted] node address 4108016 [/node being deleted]
[code end]
Process completed, Exit Code 0.
Execution time: 00:00.203
; Exit code 0 means, that all items were deleted - memory check -> ok!
Attachment:
Added attachment, named: "nasm_linkedlist_dds_sys_13dec2013.zip", contains PsPad project files, build and compile scripts, source code, description files.
Bye, Encryptor256.
-
Hello!
This is demo, my current, test version.
How to parse bencoded string, torrent file, using node list dds library.
I downloaded ubuntu torrent file and here is parse result:
[code begin]
[nodelist address: 4107856, type: 16777216, first: 4815312, last: 4815312, count: 1]
<dictionary>
<string> len: 8, announce </stream>
<string> len: 39, http://torrent.ubuntu.com:6969/announce </stream>
<string> len: 13, announce-list </stream>
<list>
<list>
<string> len: 39, http://torrent.ubuntu.com:6969/announce </stream>
<list>
<list>
<string> len: 44, http://ipv6.torrent.ubuntu.com:6969/announce </stream>
<list>
<list>
<string> len: 7, comment </stream>
<string> len: 29, Ubuntu CD releases.ubuntu.com </stream>
<string> len: 13, creation date </stream>
<integer> 1382003607 </integer>
<string> len: 4, info </stream>
<dictionary>
<string> len: 6, length </stream>
<integer> 925892608 </integer>
<string> len: 4, name </stream>
<string> len: 30, ubuntu-13.10-desktop-amd64.iso </stream>
<string> len: 12, piece length </stream>
<integer> 524288 </integer>
<string> len: 6, pieces </stream>
<string> len: 35320, ... </stream>
<dictionary>
<dictionary>
[/nodelist]
[code end]
Process completed, Exit Code 0.
Execution time: 00:00.125
Data structures:
; Bencoded node types
node_type_bstream equ (node_type_data-100)
node_type_binteger equ (node_type_data-101)
node_type_blist equ (node_type_list+100)
node_type_bdictionary equ (node_type_list+101)
; Bencoded stream node inherits node
bstreamnode.address equ (8*4)
bstreamnode.len equ (8*5)
bstreamnode_size equ (8*6)
; Bencoded integer node inherits node
bintegernode.number equ (8*4)
bintegernode_size equ (8*5)
; Bencoded list node inherits node list
; Bencoded dictionary node inherits node list
bldnode.address equ (8*7)
bldnode.len equ (8*8)
bldnode_size equ (8*9)
All this code goes into new library named: btc.
+ fixed minor glitch in dds library, procedure node.add:
; there was something like this:
pop rbp
lea rsp,[rsp+8*4]
; but should be like this:
lea rsp,[rsp+8*4]
pop rbp
Added attachment: pspad project files, build scripts, source, description, test files.
Bye, Encryptor256.