Ethereal писал(а):
Так покажите как Вы написали сами. Хочу взглянуть...
Дык, оно уже пять лет лежит все там же:
http://www.gudleifr.h1.ru/g9/g2.txt, как часть FOBOS ([url]http://www.gudleifr.h1.ru/cgi-bin/pilo.cgi?FL=../g9.txt&IS=\5.FOBOS[/url]).
Там было так (ассемблер мой, он описан в начале упомянутого файла):
Цитата:
( ПРОСТОЕ СЛОВО ДЛЯ ВЫЗОВА ПРОЦЕДУРЫ - CALL . НЕ НАДО ЗАБЫВАТЬ, ЧТО:
1. ПОЧТИ ВСЕ ФУНКЦИИ WINDOWS СТРОЯТСЯ ПО ОБРАЗЦУ PASCAL - ПАРАМЕТРЫ ИЗ
СТЕКА УДАЛЯЕТ САМА ФУНКЦИЯ;
2. СООТНЕСЕНИЕ ПЕРЕЧИСЛЕНИЯ ПАРАМЕТРОВ В СТРОКЕ C И ПОСЛЕДОВАТЕЛЬНОСТИ
КОМАНД PUSH АССЕМБЛЕРА: СЛЕВА-НАПРАВО - СНИЗУ-ВВЕРХ.
3. ВЫЗОВ МНОГИХ Ф-ИЙ ПРИВОДИТ К ВЫЗОВУ ОКОННОЙ ПРОЦЕДУРЫ )
VARIABLE EDI-OLD ( ТЕКУЩАЯ ВЕРШИНА СЛОВАРЯ, КОТОРУЮ Ф-ИЯ МОЖЕТ ИЗМЕНИТЬ)
VARIABLE EBP-OLD VARIABLE EBP-OLD2 ( ВЕРШИНА СТЕКА ВОЗВРАТОВ, КОТОРУЮ Ф-ИЯ ИЗМЕНИТЬ НЕ МОЖЕТ)
CODE CALL ( ..., a -- w)
/WO MOV, BP [DW] EBP-OLD ,
/WO MOV, DI [DW] EDI-OLD ,
CALLEW, B [RG] /DW MOV, B A [RG]
/DW MOV, DI [DW] EDI-OLD , NEXT,
END-CODE
...
\ БУФЕРА ДЛЯ ХРАНЕНИЯ MD-ЕРУНДЫ
64K ALLOCATE DROP CONSTANT WIN-STACK ( ДЛЯ ХРАНЕНИЯ КАДРОВ СТЕКА CALL-BACK-ОВ)
VARIABLE WIN-SP WIN-STACK WIN-SP !
CREATE MSG 28 ALLOT
\ ОБРАМЛЕНИЕ ОКОННОЙ ПРОЦЕДУРЫ
VARIABLE (GETMESSAGE)
USER32 Z" GetMessageA" (FUNCTION) (GETMESSAGE) !
VARIABLE (TRANSLATEMESSAGE)
USER32 Z" TranslateMessage" (FUNCTION) (TRANSLATEMESSAGE) !
VARIABLE (DISPATCHMESSAGE)
USER32 Z" DispatchMessageA" (FUNCTION) (DISPATCHMESSAGE) !
( САМОЕ ТОНКОЕ МЕСТО - СОХРАНЕНИЕ РЕГИСТРОВ и ВОССТАНОВЛЕНИЕ
SI, DI, BP И BX, ИСПОЛЬЗУЕМЫХ MUST DIE ВНУТРИ СЕБЯ)
CODE WIN-CYCLE ( -- w) ( БУДЕТ И ДРУГОЙ ВАРИАНТ - ДЛЯ ИЗВРАЩЕННЫХ ДИАЛОГОВ)
/WO MOV, DI [DW] EDI-OLD , /WO MOV, BP [DW] EBP-OLD ,
1 =H /DW XOR, A A [RG] A PUSHR, A PUSHR, A PUSHR, PUSHW, MSG ,
CALLEW, [DW] (GETMESSAGE) , /DW OR, A A [RG] ?ZR J, 2 =F
PUSHW, MSG , CALLEW, [DW] (TRANSLATEMESSAGE) ,
PUSHW, MSG , CALLEW, [DW] (DISPATCHMESSAGE) ,
JMPSHORT, 1 =B 2 =H B PUSHR, /DW MOV, B [DW] MSG 8 + ,
/DW MOV, DI [DW] EDI-OLD , NEXT, END-CODE
BEGIN-LOAD ASSEMBLER HEX
: CALL-BACK CODE ( КОНЕЧНО НЕ ДЛЯ ВСЕХ CALL-BACK-ОВ, А ТОЛЬКО ДЛЯ ОКОННЫХ)
/WO MOVA, WIN-SP ,
/WO MOV, DI A [8] 10 C, /WO MOV, SI A [8] 14 C,
/WO MOV, B A [8] 18 C, /WO MOV, BP A [8] 1C C, C POPR,
POPM, A [0] POPM, A [8] 4 C, POPM, A [8] 8 C, POPM, A [8] 0C C,
C PUSHR, /SW ADDD, A [RG] 20 C, /DW MOVA, WIN-SP ,
/DW MOV, DI [DW] EDI-OLD , /DW MOV, BP [DW] EBP-OLD ,
SI MOVRDW, >MARK NEXT, >RESOLVE END-LOAD ] ;
END-LOAD
: WIN-H WIN-SP @ 32 - @ ; ( СООБЩЕНИЕ, СОХРАНЕННОЕ В КАДРЕ СТЕКА)
: WIN-MSG WIN-SP @ 28 - @ ;
: WIN-W WIN-SP @ 24 - @ ;
: WIN-L WIN-SP @ 20 - @ ;
CODE WIN-RET
/WO MOV, BP [DW] EBP-OLD ,
A POPR, B PUSHR, ( ВОЗВРАТ ИЗ CALL-BACK)
/WO MOV, DI [DW] EDI-OLD ,
/WO MOVA, WIN-SP , /SW SUBD, A [RG] 20 C,
/DW MOV, DI A [8] 10 C, /DW MOV, SI A [8] 14 C,
/DW MOV, B A [8] 18 C, /DW MOV, BP A [8] 1C C,
/DW MOVA, WIN-SP , A POPR,
RET, END-CODE
\ ОКОННАЯ ПРОЦЕДУРА
USER32 WIN-FUNC" DEFWINDOWPROC DefWindowProcA"
USER32 WIN-FUNC" POSTQUITMESSAGE PostQuitMessage"
2 CONSTANT WM_DESTROY
: RECEPTOR ( <word> ... <;> w, wa, wa --)
CREATE ROT , SWAP , , ] ;
\ ПОЗДНЕЕ СВЯЗЫВАНИЕ РЕЦЕПТОРОВ
: RECEPTOR+ ( брат, узел --) 4 + ! ;
DOER !DESTROY
: SUBRECEPTOR+ ( сын, узел --) 8 + ! ;
( ПОСЛЕДНИЕ В СПИСКЕ ПРОВЕРЯЕМЫХ СООБЩЕНИЙ - WIN-DESTROY И WIN-DEFAULT)
0 0 0 RECEPTOR WIN-DEFAULT WIN-L WIN-W WIN-MSG WIN-H DEFWINDOWPROC CALL ;
WM_DESTROY WIN-DEFAULT 0 RECEPTOR WIN-DESTROY !DESTROY 0 POSTQUITMESSAGE CALL DROP 0 ;
VARIABLE WIN ( ПЕРЕМЕННАЯ СОДЕРЖАЩАЯ АДРЕС КОРНЯ ДЕРЕВА РАЗБОРА СООБЩЕНИЙ)
CALL-BACK WIN-PROC WIN-MSG WIN @ RECEPTING WIN-RET ; ( ОКОННАЯ Ф-ИЯ)
Основные отличия от Вашей реализации (насколько понял):
* использование дополнительного стека для регистров (чисто для наглядности),
* сохранение туда же параметров оконной ф-ии (так удобнее в больших и сложных оконных ф-иях),
* больше внимания уделено возможности рекурсивного вызова оконной ф-ии (и связи "вызывающих" и "вызываемых" FORTH-кусков),
* вместо CASE win-сообщения разбираются конечным автоматом - RECEPTING,
* в систему "сохранятелей" включен и цикл обработки сообщений.
Думаю, Вам тоже проще было написать самому, чем разобраться в написанном мной. Поэтому приводить подобные "примеры" бесполезно. Проще указать на общую идею, чему, собственно, и была посвящена тема. Сравнению идей: что во что пихать и насколько глубоко.