В этом топике было сказано много слов. По моему лучше на практике попробовать
есть ли какие проблемы, чем решать проблему еще не попробовав ее на вкус.
Я попробовал тут к своему дурацкому Фиг-форту прикрутить оконные и диалоговые
функции и очень изящно все получилось. Ввел определяющее слово CALL: для
определения оконных функций так ( синтаксис FASM ) :
Код:
ENTRY 5, 'CALL:', CALL_COLON
; A defining word used in the form:
; CALL: cccc ... ;
; Creates a word cccc, which code field is an entry point of a window or
; a dialog procedure defined as an usual colon definition with parameters
; ( lParam wParam Msg hWnd -- ... n ) , where the top stack value on exit
; n will be returned from the procedure in eax register and the other
; stack values will be discarded. The temporal return stack with 40h
; cells depth is provided for an execution of cccc.
DD DoCOLON
DD COLON ; CALL: определяем через :
;Align here in aligned model
DD LIT, 0E8h, HERE, CELL, MINUS_, C_STORE
DD ONE, ALLOT, LIT, DoWndProc_in, HERE
DD MINUS_, HERE, CELL, MINUS_, STORE_
DD SEMI_S ;Слово ;S - это EXIT Фиг-форта
DoWndProc_in: pop eax
push ebx
push esi
push edi
push ebp
push DoWndProc_out
mov ebp, esp
sub esp, 100h ;40h cells on return stack
mov esi, eax
push dword [ebp+36] ;lParam
push dword [ebp+32] ;wParam
push dword [ebp+28] ;Msg
mov ebx, [ebp+24] ;hWnd
NEXT$
DoWndProc_out: DD $+4
DD $+4
mov eax, ebx
leave
pop edi
pop esi
pop ebx
ret 10h
После чего простейшая оконная функция оказалась такой :
Код:
CALL: WndProc
( lParam wParam Msg hWnd -- ... n )
OVER
CASE
WM_DESTROY OF 0 PostQuitMessage 0 ENDOF
>R DefWindowProcA R>
ENDCASE
;
И это все.
Идея здесь такая. После определения WndProc перед ее косвенным шитым
кодом оказывается call DoWndProc_in. Этот call и есть точка входа
которую вызываеют Винды. call переправляет управление на DoWndProc_in
с адресом начала шитого кода на стеке. Я снимаю адрес шитого кода в eax.
Потом сохраняю в стек ebx esi edi. Потом опускаю esp вниз на 100h байт
- это 100h байт резервируются для стека возвратов на 64 возврата.
Причем на стек возвратов уже положен адрес DoWndProc_out. Ниже стека
возвратов остается стек данных. Я кладу на него параметры
lParam wParam Msg hWnd после чего копирую esi<-eax адрес начала шитого
кода оконной фунции и по NEXT начинаю его интерпретацию. NEXT тут
Код:
MACRO NEXT$
{
lodsd
jmp dword [eax]
}
Когда шитокодное определение оконной функции завершается, управление
улетает на DoWndProc_out. Этот код слово с вершины стека (я вершину
стека в Фиг-форте храню в ebx) пихает в eax - это будет код возврата
из оконной фунции. Далее из ebp восстанавливает esp и весь хлам со
стека улетает. Далее восстанавливает со стека ebp edi esi ebx и
завершает оконную функцию по ret 10h.
Все просто и не встретилось никаких проблем с чем-либо вообще.
P.S. Указатель стека данных в моем Фиг-форте - это esp. Указатель стека возвратов - ebp. Вершина стека данных в регистре ebx, остальное содержимое стека данных в аппаратном стеке esp.