![]() |
||
| Home | SwiftForth Archive | SwiftX Archive | |

Rick, what assumptions can be made regarding the state of the Forth
environment when COUNT-WINDOWS is executed? For example, is BASE set
to decimal?, PAD pointing to a buffer (if so how large?), which User
Variables are initialized? etc.
Also a note to beginning Windows programmers: Rick is delving deep
into the inner workings of SwiftForth here. Fortunately, knowledge of
many of these details is not required to write useful SwiftForth
programs. The API function EnumWindows may seem bizarre: a operating
system function call that repeatedly calls a function in your Forth
program. EnumWindows does, however, handle a particularly tricky
problem: how to determine the presence of all windows without a window
closing midway through your program (ie calling the API GetWindow
function in a loop).
Mike
----- Original Message -----
From: "Rick VanNorman" <rick_at_forth.com>
To: <sftalk_at_forth.com>
Sent: Tuesday, November 13, 2001 9:29 PM
Subject: [sftalk] Callbacks -- part 2
>
> --------------------------------------------------------------------
-- > Callbacks, part 2 > -------------------------------------------------------------------- -- > > Last time I explored what CB: compiled in the dictionary. Tonight, we'll > be looking at the behavior of RUNCB. This is a more complicated issue, > so please bear with me. > > When a callback is invoked by Windows, the cpu knows nothing about the > SwiftForth processor model or memory allocations or dictionary or > anything else. So, if we want to run a SwiftForth word, we must > establish all of that context as soon as the callback is run. This is > the function of RUNCB. > > We want to execute a Forth word to handle the callback, and words are > specified by their XT. So, we have to convey the XT to run to the callback. > This is the purpose of the CALL RUNCB compiled by CB: . > > Here is the code I want to examine tonight. It simply counts all of > the application windows known to the operating system. > > -------------------------------------------------------------------- -- > > -------------------------------------------------------------------- > HOW-MANY is a variable holding a count. > COUNT-WINDOWS increments the count and returns TRUE. > The line defining ALLWINDOWS compiles the following code: > > ALLWINDOWS: > CALL DOCREATE > ALLWINDOWS-DATA: > CALL RUNCB > RET #8 > NOP > DW XT-OF-COUNT-WINDOWS > > TEST zeros the counter, calls the EnumWindows api, and returns a count. > -------------------------------------------------------------------- } > > VARIABLE HOW-MANY > > : COUNT-WINDOWS ( -- flag ) 1 HOW-MANY +! 1 ; > > ' COUNT-WINDOWS 2 CB: ALLWINDOWS > > : TEST ( -- ) 0 HOW-MANY ! > ALLWINDOWS 0 EnumWindows DROP HOW-MANY @ ; > > -------------------------------------------------------------------- -- > > When we execute TEST, the address of ALLWINDOWS (which is an absolute > address of pure machine code that Windows can execute) is pushed onto > the datastack, along with a zero. This is in accordance to the api > specified for EnumWindows(). > > EnumWindows() immediately executes the callback code, building for it a > WINAPI stack frame on the processor stack. SwiftForth uses the processor > stack for its return stack -- and yes, that's where this callback is > built. We don't know where on our return stack, only that it is > guaranteed by the processor model not to overwrite the data already on > the stack. Pushed onto the stack is the zero (which could be any data > that TEST wanted to pass to the callback function) and a return address > in the Windows kernel. Execution of this portion begins at ALLWINDOWS > with a clean processor context with only an initialized processor > stack. All other registers must be assumed to be uninitialized. > > On my system, when ALLWINDOWS is executed, the return stack has the > following content: > > 77E16661 <top the return address in the windows kernel > 002B013E <top+4 the handle of the window which is being enumerated > 00000000 <top+8 the optional parameter passed to EnumWindows > > Then, RUNCB is called, which leaves the return stack looking like > > 0046E9A9 <top the address of ALLWINDOWS-DATA > 77E16661 <top+4 the return address in the windows kernel > 002B013E <top+8 the handle of the window which is being enumerated > 00000000 <top+12 the optional parameter passed to EnumWindows > > Next time, we'll pick up here and see what RUNCB actually does. > > Thanks for listening. > > Rick > > P.S. Please give feedback! Especially on things that aren't clear or > need more explainations. If you only want to say "good job" or other > very nice things that make me smile, please send those privately, not on > the list. Let's keep the bandwidth here for Forth content. > > P.P.S. Not all callbacks are immediate; some wait for events triggered > by asychronous events such as the mouse or keyboard, others wait for > specified times, still others wait for I/O completion. We'll discuss > these later. > > > -------------------------------------------------------------------- -- > sftalk_at_forth.com The SwiftForth programming discussion email list > To unsubscribe, send subject "unsubscribe sftalk" to listar_at_forth.com > For help with listar commands, send subject "help" to listar_at_forth.com > Archives are located at http://www.forth.com/sftalk -- check them out! > Search the archives! Visit http://www.forth.com/search for details. ---------------------------------------------------------------------- sftalk_at_forth.com The SwiftForth programming discussion email list To unsubscribe, send subject "unsubscribe sftalk" to listar_at_forth.com For help with listar commands, send subject "help" to listar_at_forth.com Archives are located at http://www.forth.com/sftalk -- check them out! Search the archives! Visit http://www.forth.com/search for details.Received on Wed Nov 14 2001 - 09:13:59 PST
This archive was generated by hypermail 2.2.0 : Fri Nov 21 2008 - 03:04:19 PST