Linked Lists: "The Tutorial" (for the Fixed memory linked list)

A Linked list is a series of nodes, each one containing data, and a pointer to the
next node. In this tutorial, the data is a MAX_TEXT + 1 bytes long.
Also for easy demonstration, a simple interface has been provided.

This program uses the following:
1)
  stub  DWORD

  This value is a pointer to the root of the linked list.
  It is needed in order to allow the "Return" function to work, and
  is also used in the removal of the nodes when the program exits.

2)
  current  DWORD

  This value is the pointer to the current node in the list.
  It is accessed in all three functions (Add, Next, and Return).

3)
  ACCESS_TYPE equ GPTR

  This constant is used to define how we allocate the memory
  A full definition of GPTR (and alternatives) can be found
  in the "Win32 Programmer's Reference" file.
  Basically it means allocated memory is fixed (GMEM_FIXED),
  and is initialised to zero (GMEM_ZEROINIT).
  The code does not need to be initialised to zero, but its
  safer that way ;)

4)
  MAX_TEXT equ 16

  This value defines how big the data area in the linked list
  will be. It is also used to limit the edit box in the example
  to that length, and so ensuring that we cannot try to overfill
  the data section.

What the program does:
1) The "Add" function
  In order to add a node, firstly the program decides if it has a root.
  If there is no root, then there can be no current pointer set, and so a 
  root node must be created, and current set to this newly created node.

  invoke GlobalAlloc, ACCESS_TYPE, SIZEOF NODE
  mov (NODE PTR [eax]).next, 0
  mov stub, eax
  mov current, eax

	Lines 87-90

  This code allocates the space (GlobalAlloc), allocating SIZEOF NODE bytes.
  As we are using fixed memory, the returned value from the call to
  GlobalAlloc is the pointer to the memory itself, and so we can assign this
  value to "current", and "stub".
  If the memory is created as moveable, then the return value of GlobalAlloc
  is a handle that must be locked (using the GlobalLock function) before the
  actual address of the memory can be obtained.


  Next the code gets the start address of the data section of the node, and
  then passes it to GetDlgItemText so the data section can be filled.

  lea eax, (NODE PTR [eax]).data
  invoke GetDlgItemText, hWnd, EB_DATA, eax, MAX_TEXT

	Lines 92 & 93


  The else condition is very similar, except it treats all additions to
  the list as insertions. It also does not modify the "stub", or "current"
  values, in this program all movement is dealt with in other functions for
  simplicity. It also has to ensure the "Next" button is enabled.

2) The "Return" function
  This simply resets the "current" pointer to the value of "stub" the root.
  As "current" has changed value, the text in the edit box must be changed.
  It also updates the buttons, so "Return" is disabled, and so "Next" is
  enabled.

3) The "Next" function
  This function is designed to move through the list, as it is a singly
  linked list, only moving forward through the list is possible.
  In order to move forward, "current" must become "current.next".

  mov edx, current
  mov edx, (NODE PTR [edx]).next

	Lines 129 & 130

  Although it will assemble "mov edx, (NODE PTR [current]).next" the
  result is not the same!

  The rest of this function is again concerned with the enabling, and
  disabling of buttons, and the updating of the text in the edit box.

4) Quitting
  When closing down, it is important to free up all the allocated memory!
  The code responsible for doing this is the following:

  mov edx, stub
  .REPEAT
    push (NODE PTR [edx]).next
    invoke GlobalFree, edx
    pop edx
    or edx, edx
  .UNTIL edx==0

	Lines 70-77

  It is easiest to destroy the list from root to leaf, so firstly the code
  sets edx to "stub".
  Then the code loops until edx is pointing to the null terminator.
  It is important to store the ".next" pointer before the destruction of
  the current node ("push (NODE PTR [edx]).next"), as the data will have
  gone after the call to GlobalFree. After GlobalFree has executed, the
  value of ".next" is restored to edx ready for the next loop.

THE END!
