Updated Class Libraries



While troubleshooting a problem submitted by a reader of these pages, Tom Zimmer made some suggestions. He was concerned that in several places I was using references to absolute addresses. Since these could change if an application was turnkeyed and got loaded into a different image location this could be a problem. While it turned out that this wasn't the problem, it seemed like something I should fix anyway.

The goal is to make the routines reentrant and to fill in any structures at run time and not compile time. I have chosen to fix this in a way similar to how MASM (the Microsoft Macro Assembler), and most other assemblers and compilers for that matter, handles it. MASM has a directive called LOCAL which creates a "stack frame" for handling procedures. A "stack frame" is a block of locations on the stack that can be addressed like a structure in memory. The advantage, of course, is that it is reentrant and doesn't require a fixed memory address that could change.

The basic idea for my implementation is that the Win32Forth words SP@ and SP! can be used to return addresses on the stack and to restore the stack after a stack frame structure is no longer needed. For example, suppose we want to get the rectangle for a window. We do this with a call to GetWindowRect. This function requires an address of a RECT structure and the handle of a window. The following code will do this:

\ Using a structure in memory (assume hWnd returns the window handle)

CREATE 'RECT
   0 ,   \ left
   0 ,   \ top
   0 ,   \ right
   0 ,   \ bottom

'RECT REL>ABS  hWnd  Call GetWindowRect  DROP   

\ Using a structure on the stack (assume hWnd returns the window handle)

     0 0 0 0                         \ create room for RECT results on the stack
     SP@ REL>ABS                     \ returns absolute address of the
                                     \ 4 cells we just initialized
     hWnd Call GetWindowRect  DROP   \ this fills the stack frame
                                     \ which now contains ( bottom right top left)

This may not be obvious how this works. It took me a while to see it. In Win32Forth the stack grows down in memory. Therefore, SP@, which returns the address of the top-of-stack cell, winds up returning the address of the start of a block of memory going up in memory. In the code above the four zeroes create space for 4 cells on the stack. SP@ returns the address of the start of this block.

In the updated class libraries I have defined a word called sFrame which takes as an argument the number of cells you want to reserve on the stack and returns the address of the start of this structure. In order to keep the stack properly aligned, only cell counts should be added. This shouldn't be a limit in practice since the Win32 structures also need to be aligned on cell boundries. The above example would now look like:

\ Using sFrame (assume hWnd returns the window handle)

     4 sFrame                        \ create room for RECT results on the stack
     REL>ABS                         \ returns absolute address of the
                                     \ 4 cells we just initialized
     hWnd Call GetWindowRect  DROP   \ this fills the stack frame
                                     \ which now contains ( bottom right top left)

Hopefully this isn't too confusing. Looking over the code might clarify things. If I haven't explained things well enough, let me know and I'll try to come up with a better explanation (pictures maybe?).

I have updated the class libraries and put them on a new page while I debug things. Everything seems to be working, but ya' never know. For now I'll keep the original versions around.



Author: Jeff Kelm, (how to contact me)
URL: http://www.concentric.net/~jkelm/win32for/classidx2/index.htm
(Modified: 2005-01-07)