Автор |
Сообщение |
|
|
Заголовок сообщения: |
Re: Еще один способ работы с параметрами на стеке |
 |
|
Реализовал измеритель времени однократного исполнения отдельных слов для WinFAsmForth64, сначала пишем на fasm в ядро форт-системы: Код: cfa_AHEADER 0,'xmeter',xmeter movd xmm0, eax xor eax, eax cpuid rdtsc movd xmm1, eax movd ebx, xmm0 call rbx xor eax, eax cpuid rdtsc movd ecx, xmm1 sub eax, ecx movd xmm2, eax xor eax, eax cpuid rdtsc movd xmm1, eax movd ebx, xmm0 xor eax, eax cpuid rdtsc movd ecx, xmm1 sub eax, ecx mov ebx, eax movd eax, xmm2 sub eax, ebx ret потом дописываем в уже сформированной форт-системе: Код: : dT ( "name" -- ) ' xmeter CR NIP . ." ticks " CR S0 @ SP! ; использование: Код: dT DROP результат: Код: 81 ticks
Реализовал измеритель времени однократного исполнения отдельных слов для WinFAsmForth64, сначала пишем на fasm в ядро форт-системы: [code]cfa_AHEADER 0,'xmeter',xmeter movd xmm0, eax xor eax, eax cpuid rdtsc movd xmm1, eax movd ebx, xmm0 call rbx xor eax, eax cpuid rdtsc movd ecx, xmm1 sub eax, ecx movd xmm2, eax xor eax, eax cpuid rdtsc movd xmm1, eax movd ebx, xmm0 xor eax, eax cpuid rdtsc movd ecx, xmm1 sub eax, ecx mov ebx, eax movd eax, xmm2 sub eax, ebx ret[/code] потом дописываем в уже сформированной форт-системе: [code]: dT ( "name" -- ) ' xmeter CR NIP . ." ticks " CR S0 @ SP! ;[/code] использование: [code]dT DROP[/code] результат: [code]81 ticks[/code]
|
|
|
 |
Добавлено: Вс июн 05, 2022 23:33 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Еще один способ работы с параметрами на стеке |
 |
|
Ввел для Win64FasmForth концепцию NOTFOUND - использование информации заложенной в самом имени слов для формирования кода слов. Попробовал ввести локальное именование слов с использованием NOTFOUND, получилось. Попутно ввел макросы и локально-именованные макросы. Код: REQUIRE { ~mak\locals.f \ locals \ сокращения : I: : IMMEDIATE ; I: ` [COMPILE] POSTPONE ; : d. DUP . ; : h. HEX d. DECIMAL ; : .s CR .S S0 @ SP! ;
: nfd ( a u -- ) ?SLITERAL ; : interpret_ \ -> \ меняем интерпретатор под nfd BEGIN PARSE-NAME DUP WHILE SFIND ?DUP IF STATE @ = IF COMPILE, ELSE EXECUTE THEN ELSE S" nfd" SFIND IF EXECUTE ELSE 2DROP ?SLITERAL THEN THEN ?STACK REPEAT 2DROP ; ' interpret_ &INTERPRET !
0 WARNING ! : nfd { a u } \ пребразователь символов 'c' 'cc' в число a C@ [CHAR] ' = a u + 1- C@ [CHAR] ' = AND u 3 = u 4 = OR AND 0= IF a u nfd EXIT THEN u 3 = IF a 1+ C@ ELSE a 2+ C@ 8 LSHIFT a 1+ C@ OR THEN STATE @ IF LIT, THEN ;
\ макросы : LOAD-LEX ( A U -- ) DP @ SWAP DUP ALLOT MOVE 0 C, ; : load-str ( -- a u ) 5 ALLOT DP @ >R BEGIN NextWord ( -- a u ) 2DUP 1 = \ a u a f IF C@ DUP ';' = SWAP DUP '"' = SWAP ']' = OR OR \ a u f IF 2DROP 1 ELSE OVER C@ '\' = IF DROP 0xD PARSE DROP OVER - ERASE \ a a1 a ELSE LOAD-LEX THEN 0 THEN ELSE DROP DUP 0= IF 2DROP REFILL DROP ELSE LOAD-LEX THEN 0 THEN UNTIL DP @ R@ 5 - DP ! 0xE9 C, DUP R@ - W, DUP DP ! R@ SWAP R> - 1- ; : LOAD-STR ( a u -- ) load-str DLIT, ; \ Макросы многострочные - допускают комментарии вида \ ..... : M: ( name "text ;" ) : IMMEDIATE LOAD-STR ` EVALUATE POSTPONE ; ;
\ локально-именованные: слова, макросы, переменные, массивы ( упрощенная концепция МОДУЛЕЙ ) CREATE LCODE 0xC000 ALLOT LCODE VALUE DPL \ область памяти для кода слов с локальными именами CREATE LDATA 0xC000 ALLOT LDATA VALUE LDHERE \ область памяти для локально-именованных переменных и массивов 0 VALUE XHERE VARIABLE XDPL \ переменные сохранения указателей компиляции
\ область памяти для локальных имен и их адресов 0x800 CONSTANT LENLVOC \ длина словаря CREATE ALVOC LENLVOC ALLOT BL ALVOC C! 1 VALUE LHERE
: LVOC ( -- A LEN ) ALVOC LENLVOC ; LVOC BL FILL
\ формирование локального имени ( после последнего символа имени идет символ пробела ) : lname, \ a u -- axt TUCK LHERE SWAP MOVE \ лексему в LVOC LHERE + DUP BL SWAP C! \ после лексемы записали BL 1+ DUP TO LHERE \ установить указатель в LVOC после байта BL после лексемы - туда запишем XT кода для лексемы-имени ; : L{ DPL XDPL ! HERE TO XHERE DPL DP ! ; \ переключение на компиляцию в область LCODE : }L DPL HERE XDPL @ - + TO DPL XHERE DP ! ; \ переключение на компиляцию в область CODE
: init-lvoc LVOC BL FILL LVOC DROP 1+ TO LHERE ; \ стирание локального словаря в части локальных имен, код лок. слов не удаляется : headl ( a u -- ) lname, DPL SWAP ! LHERE 5 + TO LHERE ;
M: nf1-exit { a u s } \ -- a u a u + 1- C@ s <> IF a u nfd EXIT THEN a u ; VARIABLE iol 0 iol ! \ направление ввода-вывода в locname-переменные типа value
\ начало формирования кода с локальным именем : nfd ( a u -- ) '(' nf1-exit 1- headl L{ ;
\ окончание формирования кода с локальным именем I: ) RET, }L ;
\ локально-именованные строки : nfd ( a u -- ) '"' nf1-exit 1- headl L{ LOAD-STR RET, }L ; \ name" текст строки "
\ локально-именованные макросы : nfd ( a u -- ) '[' nf1-exit 1- headl L{ LOAD-STR ` EVALUATE RET, }L ; \ name[ текст макроса ]
\ склеивание определений - локальный словарь не удаляется, слово определенное по +: добавляется в основной словарь : +: : ; : : init-lvoc : ;
\ процедура поиска имени в лок. словаре : lsearch { a u a1 u1 \ a2 } BL a1 u1 + C! a u a1 u1 1+ SEARCH >R DROP TO a2 R> IF a2 u1 TRUE ELSE a u FALSE THEN ; I: is 1 iol ! ; \ устанавливает режим записи, после исполнения записи устанавливает режим чтения
\ компиляция слов с локальными именами \ с блокировкой компиляции слов вида Name1...Name9 при совпадению \ лексем вида '1' ... '9'( числа ) из входного потока c последним символом слов NameN : nfd { a u } a C@ '1' '9' 1+ WITHIN u 1 = AND IF a u nfd EXIT THEN LVOC a u lsearch ( a u f ) 0= IF 2DROP a u nfd EXIT THEN + 1+ @ iol @ IF 19 + 0 iol ! THEN COMPILE, ; \ локально-именованные переменые : nfd ( a u -- ) \ типа value '!' nf1-exit 1- headl LDHERE LIT, ` ! L{ LDHERE LIT, ` @ RET, LDHERE LIT, ` ! RET, LDHERE 1 CELLS + TO LDHERE }L ; \ локально-именованные статические массивы : nfd ( a u -- ) \ размер задается числовым литералом [ 20 ] arr] ']' nf1-exit 1- headl L{ LDHERE LIT, RET, LDHERE + TO LDHERE }L ; \ исполнить слово или комбинатор независимо от STATE и от флага IMMEDIATE : nfd { a u } a u + 1- C@ '`' = u 1 > AND 0= IF a u nfd EXIT THEN LVOC a u 1- lsearch \ для локальных слов, определенных с использованием IMMEDIATE слов IF + 1+ @ EXECUTE ELSE a u 1- TYPE SPACE ." not found " CR THEN ; Примеры: Код: : S+ \ a1 u1 a2 u2 u2! a2! u1! a1! u1 u2 + DUP u! ALLOCATE THROW a! a1 a u1 MOVE a2 a u1 + u2 MOVE a u ; SEE S+ S" 123" S" abcd" S+ CR TYPE
: type-str str" 123456789ABCDEF " aDO[ OVER + SWAP DO ] str aDO` I C@ . LOOP ; SEE type-str CR type-str Код: CODE S+ 439528 E8 7F 03 FD FF call $4098AC ( DUP ) 43952D 48 B8 B5 B9 42 00 00 00 00 00 mov rax,$42B9B5 439537 E8 1E 07 FD FF call $409C5A ( ! ) 43953C E8 6B 03 FD FF call $4098AC ( DUP ) 439541 48 B8 BD B9 42 00 00 00 00 00 mov rax,$42B9BD 43954B E8 0A 07 FD FF call $409C5A ( ! ) 439550 E8 57 03 FD FF call $4098AC ( DUP ) 439555 48 B8 C5 B9 42 00 00 00 00 00 mov rax,$42B9C5 43955F E8 F6 06 FD FF call $409C5A ( ! ) 439564 E8 43 03 FD FF call $4098AC ( DUP ) 439569 48 B8 CD B9 42 00 00 00 00 00 mov rax,$42B9CD 439573 E8 E2 06 FD FF call $409C5A ( ! ) 439578 E8 1C 64 FE FF call $41F999 ( LCODE+59 ) 43957D E8 C3 63 FE FF call $41F945 ( LCODE+5 ) 439582 E8 BB 11 FD FF call $40A742 ( + ) 439587 E8 20 03 FD FF call $4098AC ( DUP ) 43958C E8 1B 03 FD FF call $4098AC ( DUP ) 439591 48 B8 D5 B9 42 00 00 00 00 00 mov rax,$42B9D5 43959B E8 BA 06 FD FF call $409C5A ( ! ) 4395A0 E8 3C 27 FD FF call $40BCE1 ( ALLOCATE ) 4395A5 E8 14 B2 FC FF call $4047BE ( THROW ) 4395AA E8 FD 02 FD FF call $4098AC ( DUP ) 4395AF 48 B8 DD B9 42 00 00 00 00 00 mov rax,$42B9DD 4395B9 E8 9C 06 FD FF call $409C5A ( ! ) 4395BE E8 00 64 FE FF call $41F9C3 ( LCODE+83 ) 4395C3 E8 4F 64 FE FF call $41FA17 ( LCODE+D7 ) 4395C8 E8 CC 63 FE FF call $41F999 ( LCODE+59 ) 4395CD E8 6B FA FC FF call $40903D ( MOVE ) 4395D2 E8 98 63 FE FF call $41F96F ( LCODE+2F ) 4395D7 E8 3B 64 FE FF call $41FA17 ( LCODE+D7 ) 4395DC E8 B8 63 FE FF call $41F999 ( LCODE+59 ) 4395E1 E8 5C 11 FD FF call $40A742 ( + ) 4395E6 E8 5A 63 FE FF call $41F945 ( LCODE+5 ) 4395EB E8 4D FA FC FF call $40903D ( MOVE ) 4395F0 E8 22 64 FE FF call $41FA17 ( LCODE+D7 ) 4395F5 E8 F3 63 FE FF call $41F9ED ( LCODE+AD ) 4395FA C3 ret END-CODE ( 211 bytes, 37 instructions )
123abcd
CODE type-str 439628 E8 14 64 FE FF call $41FA41 ( LCODE+101 ) 43962D E8 23 03 FD FF call $409955 ( OVER ) 439632 E8 0B 11 FD FF call $40A742 ( + ) 439637 E8 E9 02 FD FF call $409925 ( SWAP ) 43963C E8 D3 16 FD FF call $40AD14 ( XDO ) 439641 68 61 96 43 00 push $439661 439646 52 push edx 439647 53 push ebx 439648 E8 05 16 FD FF call $40AC52 ( I ) 43964D E8 69 05 FD FF call $409BBB ( C@ ) 439652 E8 93 A9 FC FF call $403FEA ( . ) 439657 FF 04 24 inc dword PTR [esp] 43965A 71 EC jNo $439648 43965C 48 8D 64 24 18 lea rsp,$18[rsp] 439661 C3 ret END-CODE ( 58 bytes, 15 instructions )
49 50 51 52 53 54 55 56 57 65 66 67 68 69 70 Внутренности locname слова str Код: $41FA41 see
CODE call 41FA41 41FA41 E9 10 00 00 00 jmp $41FA56 ( LCODE+116 ) 41FA46 31 32 33 34 35 36 37 38 39 41 42 43 44 45 46 00 123456789ABCDEF. 41FA56 E8 51 9E FE FF call $4098AC ( DUP ) 41FA5B 48 B8 46 FA 41 00 00 00 00 00 mov rax,$41FA46 41FA65 E8 42 9E FE FF call $4098AC ( DUP ) 41FA6A 48 B8 0F 00 00 00 00 00 00 00 mov rax,$F 41FA74 C3 ret END-CODE ( 52 bytes, 6 instructions )
Ввел для Win64FasmForth концепцию NOTFOUND - использование информации заложенной в самом имени слов для формирования кода слов. Попробовал ввести локальное именование слов с использованием NOTFOUND, получилось. Попутно ввел макросы и локально-именованные макросы. [code]REQUIRE { ~mak\locals.f \ locals \ сокращения : I: : IMMEDIATE ; I: ` [COMPILE] POSTPONE ; : d. DUP . ; : h. HEX d. DECIMAL ; : .s CR .S S0 @ SP! ;
: nfd ( a u -- ) ?SLITERAL ; : interpret_ \ -> \ меняем интерпретатор под nfd BEGIN PARSE-NAME DUP WHILE SFIND ?DUP IF STATE @ = IF COMPILE, ELSE EXECUTE THEN ELSE S" nfd" SFIND IF EXECUTE ELSE 2DROP ?SLITERAL THEN THEN ?STACK REPEAT 2DROP ; ' interpret_ &INTERPRET !
0 WARNING ! : nfd { a u } \ пребразователь символов 'c' 'cc' в число a C@ [CHAR] ' = a u + 1- C@ [CHAR] ' = AND u 3 = u 4 = OR AND 0= IF a u nfd EXIT THEN u 3 = IF a 1+ C@ ELSE a 2+ C@ 8 LSHIFT a 1+ C@ OR THEN STATE @ IF LIT, THEN ;
\ макросы : LOAD-LEX ( A U -- ) DP @ SWAP DUP ALLOT MOVE 0 C, ; : load-str ( -- a u ) 5 ALLOT DP @ >R BEGIN NextWord ( -- a u ) 2DUP 1 = \ a u a f IF C@ DUP ';' = SWAP DUP '"' = SWAP ']' = OR OR \ a u f IF 2DROP 1 ELSE OVER C@ '\' = IF DROP 0xD PARSE DROP OVER - ERASE \ a a1 a ELSE LOAD-LEX THEN 0 THEN ELSE DROP DUP 0= IF 2DROP REFILL DROP ELSE LOAD-LEX THEN 0 THEN UNTIL DP @ R@ 5 - DP ! 0xE9 C, DUP R@ - W, DUP DP ! R@ SWAP R> - 1- ; : LOAD-STR ( a u -- ) load-str DLIT, ; \ Макросы многострочные - допускают комментарии вида \ ..... : M: ( name "text ;" ) : IMMEDIATE LOAD-STR ` EVALUATE POSTPONE ; ;
\ локально-именованные: слова, макросы, переменные, массивы ( упрощенная концепция МОДУЛЕЙ ) CREATE LCODE 0xC000 ALLOT LCODE VALUE DPL \ область памяти для кода слов с локальными именами CREATE LDATA 0xC000 ALLOT LDATA VALUE LDHERE \ область памяти для локально-именованных переменных и массивов 0 VALUE XHERE VARIABLE XDPL \ переменные сохранения указателей компиляции
\ область памяти для локальных имен и их адресов 0x800 CONSTANT LENLVOC \ длина словаря CREATE ALVOC LENLVOC ALLOT BL ALVOC C! 1 VALUE LHERE
: LVOC ( -- A LEN ) ALVOC LENLVOC ; LVOC BL FILL
\ формирование локального имени ( после последнего символа имени идет символ пробела ) : lname, \ a u -- axt TUCK LHERE SWAP MOVE \ лексему в LVOC LHERE + DUP BL SWAP C! \ после лексемы записали BL 1+ DUP TO LHERE \ установить указатель в LVOC после байта BL после лексемы - туда запишем XT кода для лексемы-имени ; : L{ DPL XDPL ! HERE TO XHERE DPL DP ! ; \ переключение на компиляцию в область LCODE : }L DPL HERE XDPL @ - + TO DPL XHERE DP ! ; \ переключение на компиляцию в область CODE
: init-lvoc LVOC BL FILL LVOC DROP 1+ TO LHERE ; \ стирание локального словаря в части локальных имен, код лок. слов не удаляется : headl ( a u -- ) lname, DPL SWAP ! LHERE 5 + TO LHERE ;
M: nf1-exit { a u s } \ -- a u a u + 1- C@ s <> IF a u nfd EXIT THEN a u ; VARIABLE iol 0 iol ! \ направление ввода-вывода в locname-переменные типа value
\ начало формирования кода с локальным именем : nfd ( a u -- ) '(' nf1-exit 1- headl L{ ;
\ окончание формирования кода с локальным именем I: ) RET, }L ;
\ локально-именованные строки : nfd ( a u -- ) '"' nf1-exit 1- headl L{ LOAD-STR RET, }L ; \ name" текст строки "
\ локально-именованные макросы : nfd ( a u -- ) '[' nf1-exit 1- headl L{ LOAD-STR ` EVALUATE RET, }L ; \ name[ текст макроса ]
\ склеивание определений - локальный словарь не удаляется, слово определенное по +: добавляется в основной словарь : +: : ; : : init-lvoc : ;
\ процедура поиска имени в лок. словаре : lsearch { a u a1 u1 \ a2 } BL a1 u1 + C! a u a1 u1 1+ SEARCH >R DROP TO a2 R> IF a2 u1 TRUE ELSE a u FALSE THEN ; I: is 1 iol ! ; \ устанавливает режим записи, после исполнения записи устанавливает режим чтения
\ компиляция слов с локальными именами \ с блокировкой компиляции слов вида Name1...Name9 при совпадению \ лексем вида '1' ... '9'( числа ) из входного потока c последним символом слов NameN : nfd { a u } a C@ '1' '9' 1+ WITHIN u 1 = AND IF a u nfd EXIT THEN LVOC a u lsearch ( a u f ) 0= IF 2DROP a u nfd EXIT THEN + 1+ @ iol @ IF 19 + 0 iol ! THEN COMPILE, ; \ локально-именованные переменые : nfd ( a u -- ) \ типа value '!' nf1-exit 1- headl LDHERE LIT, ` ! L{ LDHERE LIT, ` @ RET, LDHERE LIT, ` ! RET, LDHERE 1 CELLS + TO LDHERE }L ; \ локально-именованные статические массивы : nfd ( a u -- ) \ размер задается числовым литералом [ 20 ] arr] ']' nf1-exit 1- headl L{ LDHERE LIT, RET, LDHERE + TO LDHERE }L ; \ исполнить слово или комбинатор независимо от STATE и от флага IMMEDIATE : nfd { a u } a u + 1- C@ '`' = u 1 > AND 0= IF a u nfd EXIT THEN LVOC a u 1- lsearch \ для локальных слов, определенных с использованием IMMEDIATE слов IF + 1+ @ EXECUTE ELSE a u 1- TYPE SPACE ." not found " CR THEN ;[/code]
Примеры: [code]: S+ \ a1 u1 a2 u2 u2! a2! u1! a1! u1 u2 + DUP u! ALLOCATE THROW a! a1 a u1 MOVE a2 a u1 + u2 MOVE a u ; SEE S+ S" 123" S" abcd" S+ CR TYPE
: type-str str" 123456789ABCDEF " aDO[ OVER + SWAP DO ] str aDO` I C@ . LOOP ; SEE type-str CR type-str[/code] [code]CODE S+ 439528 E8 7F 03 FD FF call $4098AC ( DUP ) 43952D 48 B8 B5 B9 42 00 00 00 00 00 mov rax,$42B9B5 439537 E8 1E 07 FD FF call $409C5A ( ! ) 43953C E8 6B 03 FD FF call $4098AC ( DUP ) 439541 48 B8 BD B9 42 00 00 00 00 00 mov rax,$42B9BD 43954B E8 0A 07 FD FF call $409C5A ( ! ) 439550 E8 57 03 FD FF call $4098AC ( DUP ) 439555 48 B8 C5 B9 42 00 00 00 00 00 mov rax,$42B9C5 43955F E8 F6 06 FD FF call $409C5A ( ! ) 439564 E8 43 03 FD FF call $4098AC ( DUP ) 439569 48 B8 CD B9 42 00 00 00 00 00 mov rax,$42B9CD 439573 E8 E2 06 FD FF call $409C5A ( ! ) 439578 E8 1C 64 FE FF call $41F999 ( LCODE+59 ) 43957D E8 C3 63 FE FF call $41F945 ( LCODE+5 ) 439582 E8 BB 11 FD FF call $40A742 ( + ) 439587 E8 20 03 FD FF call $4098AC ( DUP ) 43958C E8 1B 03 FD FF call $4098AC ( DUP ) 439591 48 B8 D5 B9 42 00 00 00 00 00 mov rax,$42B9D5 43959B E8 BA 06 FD FF call $409C5A ( ! ) 4395A0 E8 3C 27 FD FF call $40BCE1 ( ALLOCATE ) 4395A5 E8 14 B2 FC FF call $4047BE ( THROW ) 4395AA E8 FD 02 FD FF call $4098AC ( DUP ) 4395AF 48 B8 DD B9 42 00 00 00 00 00 mov rax,$42B9DD 4395B9 E8 9C 06 FD FF call $409C5A ( ! ) 4395BE E8 00 64 FE FF call $41F9C3 ( LCODE+83 ) 4395C3 E8 4F 64 FE FF call $41FA17 ( LCODE+D7 ) 4395C8 E8 CC 63 FE FF call $41F999 ( LCODE+59 ) 4395CD E8 6B FA FC FF call $40903D ( MOVE ) 4395D2 E8 98 63 FE FF call $41F96F ( LCODE+2F ) 4395D7 E8 3B 64 FE FF call $41FA17 ( LCODE+D7 ) 4395DC E8 B8 63 FE FF call $41F999 ( LCODE+59 ) 4395E1 E8 5C 11 FD FF call $40A742 ( + ) 4395E6 E8 5A 63 FE FF call $41F945 ( LCODE+5 ) 4395EB E8 4D FA FC FF call $40903D ( MOVE ) 4395F0 E8 22 64 FE FF call $41FA17 ( LCODE+D7 ) 4395F5 E8 F3 63 FE FF call $41F9ED ( LCODE+AD ) 4395FA C3 ret END-CODE ( 211 bytes, 37 instructions )
123abcd
CODE type-str 439628 E8 14 64 FE FF call $41FA41 ( LCODE+101 ) 43962D E8 23 03 FD FF call $409955 ( OVER ) 439632 E8 0B 11 FD FF call $40A742 ( + ) 439637 E8 E9 02 FD FF call $409925 ( SWAP ) 43963C E8 D3 16 FD FF call $40AD14 ( XDO ) 439641 68 61 96 43 00 push $439661 439646 52 push edx 439647 53 push ebx 439648 E8 05 16 FD FF call $40AC52 ( I ) 43964D E8 69 05 FD FF call $409BBB ( C@ ) 439652 E8 93 A9 FC FF call $403FEA ( . ) 439657 FF 04 24 inc dword PTR [esp] 43965A 71 EC jNo $439648 43965C 48 8D 64 24 18 lea rsp,$18[rsp] 439661 C3 ret END-CODE ( 58 bytes, 15 instructions )
49 50 51 52 53 54 55 56 57 65 66 67 68 69 70[/code] Внутренности locname слова str [code]$41FA41 see
CODE call 41FA41 41FA41 E9 10 00 00 00 jmp $41FA56 ( LCODE+116 ) 41FA46 31 32 33 34 35 36 37 38 39 41 42 43 44 45 46 00 123456789ABCDEF. 41FA56 E8 51 9E FE FF call $4098AC ( DUP ) 41FA5B 48 B8 46 FA 41 00 00 00 00 00 mov rax,$41FA46 41FA65 E8 42 9E FE FF call $4098AC ( DUP ) 41FA6A 48 B8 0F 00 00 00 00 00 00 00 mov rax,$F 41FA74 C3 ret END-CODE ( 52 bytes, 6 instructions )[/code]
|
|
|
 |
Добавлено: Пн май 30, 2022 10:04 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Еще один способ работы с параметрами на стеке |
 |
|
Вариант реализации локальных переменных без использования хипа и стека возвратов с использованием только стека параметров на основе выражений типа стексов. Этот вариант вполне подошел также и для Win64FasmForth ( 64-разрядная форт-система для Windows ) в качестве оптимизатора, которого в Win64FasmForth нет. Пример: Код: : S+ { a1 u1 a2 u2 \ a u } u1 u2 + DUP TO u ALLOCATE THROW TO a a1 a u1 MOVE a2 a u1 + u2 MOVE a u ; SEE S+ S" 123 " S" abc" S+ CR TYPE
: s+ ( a1 u1 a2 u2 -- a u ) 4$24 + ALLOCATE THROW 5$152 MOVE 5|5243452 + 2|21 MOVE + ; SEE s+ S" 123 " S" abc" s+ CR TYPE
CODE S+ 435F58 E8 4F 39 FD FF call $4098AC ( DUP ) 435F5D 48 B8 00 00 00 00 00 00 00 00 mov rax,$0 435F67 E8 CF 48 FD FF call $40A83B ( >R ) 435F6C E8 3B 39 FD FF call $4098AC ( DUP ) 435F71 48 B8 00 00 00 00 00 00 00 00 mov rax,$0 435F7B E8 BB 48 FD FF call $40A83B ( >R ) 435F80 E8 B6 48 FD FF call $40A83B ( >R ) 435F85 E8 B1 48 FD FF call $40A83B ( >R ) 435F8A E8 AC 48 FD FF call $40A83B ( >R ) 435F8F E8 A7 48 FD FF call $40A83B ( >R ) 435F94 E8 13 39 FD FF call $4098AC ( DUP ) 435F99 48 B8 30 00 00 00 00 00 00 00 mov rax,$30 435FA3 E8 93 48 FD FF call $40A83B ( >R ) 435FA8 E8 FF 38 FD FF call $4098AC ( DUP ) 435FAD 48 B8 8C BE 40 00 00 00 00 00 mov rax,$40BE8C 435FB7 E8 7F 48 FD FF call $40A83B ( >R ) 435FBC E8 EB 38 FD FF call $4098AC ( DUP ) 435FC1 48 B8 18 00 00 00 00 00 00 00 mov rax,$18 435FCB E8 B4 49 FD FF call $40A984 ( RP@ ) 435FD0 E8 6D 47 FD FF call $40A742 ( + ) 435FD5 E8 A0 3B FD FF call $409B7A ( @ ) 435FDA E8 CD 38 FD FF call $4098AC ( DUP ) 435FDF 48 B8 28 00 00 00 00 00 00 00 mov rax,$28 435FE9 E8 96 49 FD FF call $40A984 ( RP@ ) 435FEE E8 4F 47 FD FF call $40A742 ( + ) 435FF3 E8 82 3B FD FF call $409B7A ( @ ) 435FF8 E8 45 47 FD FF call $40A742 ( + ) 435FFD E8 AA 38 FD FF call $4098AC ( DUP ) 436002 E8 A5 38 FD FF call $4098AC ( DUP ) 436007 48 B8 38 00 00 00 00 00 00 00 mov rax,$38 436011 E8 6E 49 FD FF call $40A984 ( RP@ ) 436016 E8 27 47 FD FF call $40A742 ( + ) 43601B E8 3A 3C FD FF call $409C5A ( ! ) 436020 E8 BC 5C FD FF call $40BCE1 ( ALLOCATE ) 436025 E8 94 E7 FC FF call $4047BE ( THROW ) 43602A E8 7D 38 FD FF call $4098AC ( DUP ) 43602F 48 B8 30 00 00 00 00 00 00 00 mov rax,$30 436039 E8 46 49 FD FF call $40A984 ( RP@ ) 43603E E8 FF 46 FD FF call $40A742 ( + ) 436043 E8 12 3C FD FF call $409C5A ( ! ) 436048 E8 5F 38 FD FF call $4098AC ( DUP ) 43604D 48 B8 10 00 00 00 00 00 00 00 mov rax,$10 436057 E8 28 49 FD FF call $40A984 ( RP@ ) 43605C E8 E1 46 FD FF call $40A742 ( + ) 436061 E8 14 3B FD FF call $409B7A ( @ ) 436066 E8 41 38 FD FF call $4098AC ( DUP ) 43606B 48 B8 30 00 00 00 00 00 00 00 mov rax,$30 436075 E8 0A 49 FD FF call $40A984 ( RP@ ) 43607A E8 C3 46 FD FF call $40A742 ( + ) 43607F E8 F6 3A FD FF call $409B7A ( @ ) 436084 E8 23 38 FD FF call $4098AC ( DUP ) 436089 48 B8 18 00 00 00 00 00 00 00 mov rax,$18 436093 E8 EC 48 FD FF call $40A984 ( RP@ ) 436098 E8 A5 46 FD FF call $40A742 ( + ) 43609D E8 D8 3A FD FF call $409B7A ( @ ) 4360A2 E8 96 2F FD FF call $40903D ( MOVE ) 4360A7 E8 00 38 FD FF call $4098AC ( DUP ) 4360AC 48 B8 20 00 00 00 00 00 00 00 mov rax,$20 4360B6 E8 C9 48 FD FF call $40A984 ( RP@ ) 4360BB E8 82 46 FD FF call $40A742 ( + ) 4360C0 E8 B5 3A FD FF call $409B7A ( @ ) 4360C5 E8 E2 37 FD FF call $4098AC ( DUP ) 4360CA 48 B8 30 00 00 00 00 00 00 00 mov rax,$30 4360D4 E8 AB 48 FD FF call $40A984 ( RP@ ) 4360D9 E8 64 46 FD FF call $40A742 ( + ) 4360DE E8 97 3A FD FF call $409B7A ( @ ) 4360E3 E8 C4 37 FD FF call $4098AC ( DUP ) 4360E8 48 B8 18 00 00 00 00 00 00 00 mov rax,$18 4360F2 E8 8D 48 FD FF call $40A984 ( RP@ ) 4360F7 E8 46 46 FD FF call $40A742 ( + ) 4360FC E8 79 3A FD FF call $409B7A ( @ ) 436101 E8 3C 46 FD FF call $40A742 ( + ) 436106 E8 A1 37 FD FF call $4098AC ( DUP ) 43610B 48 B8 28 00 00 00 00 00 00 00 mov rax,$28 436115 E8 6A 48 FD FF call $40A984 ( RP@ ) 43611A E8 23 46 FD FF call $40A742 ( + ) 43611F E8 56 3A FD FF call $409B7A ( @ ) 436124 E8 14 2F FD FF call $40903D ( MOVE ) 436129 E8 7E 37 FD FF call $4098AC ( DUP ) 43612E 48 B8 30 00 00 00 00 00 00 00 mov rax,$30 436138 E8 47 48 FD FF call $40A984 ( RP@ ) 43613D E8 00 46 FD FF call $40A742 ( + ) 436142 E8 33 3A FD FF call $409B7A ( @ ) 436147 E8 60 37 FD FF call $4098AC ( DUP ) 43614C 48 B8 38 00 00 00 00 00 00 00 mov rax,$38 436156 E8 29 48 FD FF call $40A984 ( RP@ ) 43615B E8 E2 45 FD FF call $40A742 ( + ) 436160 E8 15 3A FD FF call $409B7A ( @ ) 436165 C3 ret END-CODE ( 526 bytes, 89 instructions )
123 abc
CODE s+ 436190 48 8B 4D 08 mov rcx,$08[rbp] 436194 48 89 45 F8 mov -$08[rbp],rax 436198 48 89 4D F0 mov -$10[rbp],rcx 43619C 48 8D 6D F0 lea rbp,-$10[rbp] 4361A0 E8 9D 45 FD FF call $40A742 ( + ) 4361A5 E8 37 5B FD FF call $40BCE1 ( ALLOCATE ) 4361AA E8 0F E6 FC FF call $4047BE ( THROW ) 4361AF 48 8B 5D 18 mov rbx,$18[rbp] 4361B3 48 89 45 F8 mov -$08[rbp],rax 4361B7 48 89 45 E8 mov -$18[rbp],rax 4361BB 48 8B 45 10 mov rax,$10[rbp] 4361BF 48 89 5D F0 mov -$10[rbp],rbx 4361C3 48 8D 6D E8 lea rbp,-$18[rbp] 4361C7 E8 71 2E FD FF call $40903D ( MOVE ) 4361CC 48 8B 55 08 mov rdx,$08[rbp] 4361D0 48 8B 75 00 mov rsi,$00[rbp] 4361D4 48 89 45 18 mov $18[rbp],rax 4361D8 48 89 45 F0 mov -$10[rbp],rax 4361DC 48 8B 45 10 mov rax,$10[rbp] 4361E0 48 89 75 08 mov $08[rbp],rsi 4361E4 48 89 55 00 mov $00[rbp],rdx 4361E8 48 89 75 F8 mov -$08[rbp],rsi 4361EC 48 8D 6D F0 lea rbp,-$10[rbp] 4361F0 E8 4D 45 FD FF call $40A742 ( + ) 4361F5 48 8B 5D 00 mov rbx,$00[rbp] 4361F9 48 89 45 00 mov $00[rbp],rax 4361FD 48 8B C3 mov rax,rbx 436200 E8 38 2E FD FF call $40903D ( MOVE ) 436205 E8 38 45 FD FF call $40A742 ( + ) 43620A C3 ret END-CODE ( 123 bytes, 30 instructions )
123 abc
PS. Оптимизация происходит как по объему кода так и по времени выполнения. Здесь используются две формы записи: Основная, например 5|5243452 ( 1 2 3 4 5 --> 5 2 4 3 4 5 2 ) Сокращенная 4$24 ( соответствует 4|123424 в основной форме )
Вариант реализации локальных переменных без использования хипа и стека возвратов с использованием только стека параметров на основе выражений типа стексов. Этот вариант вполне подошел также и для Win64FasmForth ( 64-разрядная форт-система для Windows ) в качестве оптимизатора, которого в Win64FasmForth нет. Пример:
[code]: S+ { a1 u1 a2 u2 \ a u } u1 u2 + DUP TO u ALLOCATE THROW TO a a1 a u1 MOVE a2 a u1 + u2 MOVE a u ; SEE S+ S" 123 " S" abc" S+ CR TYPE
: s+ ( a1 u1 a2 u2 -- a u ) 4$24 + ALLOCATE THROW 5$152 MOVE 5|5243452 + 2|21 MOVE + ; SEE s+ S" 123 " S" abc" s+ CR TYPE
CODE S+ 435F58 E8 4F 39 FD FF call $4098AC ( DUP ) 435F5D 48 B8 00 00 00 00 00 00 00 00 mov rax,$0 435F67 E8 CF 48 FD FF call $40A83B ( >R ) 435F6C E8 3B 39 FD FF call $4098AC ( DUP ) 435F71 48 B8 00 00 00 00 00 00 00 00 mov rax,$0 435F7B E8 BB 48 FD FF call $40A83B ( >R ) 435F80 E8 B6 48 FD FF call $40A83B ( >R ) 435F85 E8 B1 48 FD FF call $40A83B ( >R ) 435F8A E8 AC 48 FD FF call $40A83B ( >R ) 435F8F E8 A7 48 FD FF call $40A83B ( >R ) 435F94 E8 13 39 FD FF call $4098AC ( DUP ) 435F99 48 B8 30 00 00 00 00 00 00 00 mov rax,$30 435FA3 E8 93 48 FD FF call $40A83B ( >R ) 435FA8 E8 FF 38 FD FF call $4098AC ( DUP ) 435FAD 48 B8 8C BE 40 00 00 00 00 00 mov rax,$40BE8C 435FB7 E8 7F 48 FD FF call $40A83B ( >R ) 435FBC E8 EB 38 FD FF call $4098AC ( DUP ) 435FC1 48 B8 18 00 00 00 00 00 00 00 mov rax,$18 435FCB E8 B4 49 FD FF call $40A984 ( RP@ ) 435FD0 E8 6D 47 FD FF call $40A742 ( + ) 435FD5 E8 A0 3B FD FF call $409B7A ( @ ) 435FDA E8 CD 38 FD FF call $4098AC ( DUP ) 435FDF 48 B8 28 00 00 00 00 00 00 00 mov rax,$28 435FE9 E8 96 49 FD FF call $40A984 ( RP@ ) 435FEE E8 4F 47 FD FF call $40A742 ( + ) 435FF3 E8 82 3B FD FF call $409B7A ( @ ) 435FF8 E8 45 47 FD FF call $40A742 ( + ) 435FFD E8 AA 38 FD FF call $4098AC ( DUP ) 436002 E8 A5 38 FD FF call $4098AC ( DUP ) 436007 48 B8 38 00 00 00 00 00 00 00 mov rax,$38 436011 E8 6E 49 FD FF call $40A984 ( RP@ ) 436016 E8 27 47 FD FF call $40A742 ( + ) 43601B E8 3A 3C FD FF call $409C5A ( ! ) 436020 E8 BC 5C FD FF call $40BCE1 ( ALLOCATE ) 436025 E8 94 E7 FC FF call $4047BE ( THROW ) 43602A E8 7D 38 FD FF call $4098AC ( DUP ) 43602F 48 B8 30 00 00 00 00 00 00 00 mov rax,$30 436039 E8 46 49 FD FF call $40A984 ( RP@ ) 43603E E8 FF 46 FD FF call $40A742 ( + ) 436043 E8 12 3C FD FF call $409C5A ( ! ) 436048 E8 5F 38 FD FF call $4098AC ( DUP ) 43604D 48 B8 10 00 00 00 00 00 00 00 mov rax,$10 436057 E8 28 49 FD FF call $40A984 ( RP@ ) 43605C E8 E1 46 FD FF call $40A742 ( + ) 436061 E8 14 3B FD FF call $409B7A ( @ ) 436066 E8 41 38 FD FF call $4098AC ( DUP ) 43606B 48 B8 30 00 00 00 00 00 00 00 mov rax,$30 436075 E8 0A 49 FD FF call $40A984 ( RP@ ) 43607A E8 C3 46 FD FF call $40A742 ( + ) 43607F E8 F6 3A FD FF call $409B7A ( @ ) 436084 E8 23 38 FD FF call $4098AC ( DUP ) 436089 48 B8 18 00 00 00 00 00 00 00 mov rax,$18 436093 E8 EC 48 FD FF call $40A984 ( RP@ ) 436098 E8 A5 46 FD FF call $40A742 ( + ) 43609D E8 D8 3A FD FF call $409B7A ( @ ) 4360A2 E8 96 2F FD FF call $40903D ( MOVE ) 4360A7 E8 00 38 FD FF call $4098AC ( DUP ) 4360AC 48 B8 20 00 00 00 00 00 00 00 mov rax,$20 4360B6 E8 C9 48 FD FF call $40A984 ( RP@ ) 4360BB E8 82 46 FD FF call $40A742 ( + ) 4360C0 E8 B5 3A FD FF call $409B7A ( @ ) 4360C5 E8 E2 37 FD FF call $4098AC ( DUP ) 4360CA 48 B8 30 00 00 00 00 00 00 00 mov rax,$30 4360D4 E8 AB 48 FD FF call $40A984 ( RP@ ) 4360D9 E8 64 46 FD FF call $40A742 ( + ) 4360DE E8 97 3A FD FF call $409B7A ( @ ) 4360E3 E8 C4 37 FD FF call $4098AC ( DUP ) 4360E8 48 B8 18 00 00 00 00 00 00 00 mov rax,$18 4360F2 E8 8D 48 FD FF call $40A984 ( RP@ ) 4360F7 E8 46 46 FD FF call $40A742 ( + ) 4360FC E8 79 3A FD FF call $409B7A ( @ ) 436101 E8 3C 46 FD FF call $40A742 ( + ) 436106 E8 A1 37 FD FF call $4098AC ( DUP ) 43610B 48 B8 28 00 00 00 00 00 00 00 mov rax,$28 436115 E8 6A 48 FD FF call $40A984 ( RP@ ) 43611A E8 23 46 FD FF call $40A742 ( + ) 43611F E8 56 3A FD FF call $409B7A ( @ ) 436124 E8 14 2F FD FF call $40903D ( MOVE ) 436129 E8 7E 37 FD FF call $4098AC ( DUP ) 43612E 48 B8 30 00 00 00 00 00 00 00 mov rax,$30 436138 E8 47 48 FD FF call $40A984 ( RP@ ) 43613D E8 00 46 FD FF call $40A742 ( + ) 436142 E8 33 3A FD FF call $409B7A ( @ ) 436147 E8 60 37 FD FF call $4098AC ( DUP ) 43614C 48 B8 38 00 00 00 00 00 00 00 mov rax,$38 436156 E8 29 48 FD FF call $40A984 ( RP@ ) 43615B E8 E2 45 FD FF call $40A742 ( + ) 436160 E8 15 3A FD FF call $409B7A ( @ ) 436165 C3 ret END-CODE ( 526 bytes, 89 instructions )
123 abc
CODE s+ 436190 48 8B 4D 08 mov rcx,$08[rbp] 436194 48 89 45 F8 mov -$08[rbp],rax 436198 48 89 4D F0 mov -$10[rbp],rcx 43619C 48 8D 6D F0 lea rbp,-$10[rbp] 4361A0 E8 9D 45 FD FF call $40A742 ( + ) 4361A5 E8 37 5B FD FF call $40BCE1 ( ALLOCATE ) 4361AA E8 0F E6 FC FF call $4047BE ( THROW ) 4361AF 48 8B 5D 18 mov rbx,$18[rbp] 4361B3 48 89 45 F8 mov -$08[rbp],rax 4361B7 48 89 45 E8 mov -$18[rbp],rax 4361BB 48 8B 45 10 mov rax,$10[rbp] 4361BF 48 89 5D F0 mov -$10[rbp],rbx 4361C3 48 8D 6D E8 lea rbp,-$18[rbp] 4361C7 E8 71 2E FD FF call $40903D ( MOVE ) 4361CC 48 8B 55 08 mov rdx,$08[rbp] 4361D0 48 8B 75 00 mov rsi,$00[rbp] 4361D4 48 89 45 18 mov $18[rbp],rax 4361D8 48 89 45 F0 mov -$10[rbp],rax 4361DC 48 8B 45 10 mov rax,$10[rbp] 4361E0 48 89 75 08 mov $08[rbp],rsi 4361E4 48 89 55 00 mov $00[rbp],rdx 4361E8 48 89 75 F8 mov -$08[rbp],rsi 4361EC 48 8D 6D F0 lea rbp,-$10[rbp] 4361F0 E8 4D 45 FD FF call $40A742 ( + ) 4361F5 48 8B 5D 00 mov rbx,$00[rbp] 4361F9 48 89 45 00 mov $00[rbp],rax 4361FD 48 8B C3 mov rax,rbx 436200 E8 38 2E FD FF call $40903D ( MOVE ) 436205 E8 38 45 FD FF call $40A742 ( + ) 43620A C3 ret END-CODE ( 123 bytes, 30 instructions )
123 abc [/code] PS. Оптимизация происходит как по объему кода так и по времени выполнения. Здесь используются две формы записи: Основная, например 5|5243452 ( 1 2 3 4 5 --> 5 2 4 3 4 5 2 ) Сокращенная 4$24 ( соответствует 4|123424 в основной форме )
|
|
|
 |
Добавлено: Ср май 18, 2022 22:21 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Еще один способ работы с параметрами на стеке |
 |
|
Victor__v писал(а): Как понимаю, Вы закидываете часть переменных выше вершины стека. Но как происходит контроль измерения глубины? При изменении этого самого стека? Ничего никуда не закидывается. В начале манипулятора просто отмечается с каким количеством верхних параметров на стеке будет работать данный манипулятор. Вот на стеке находятся 4 параметра: a b c d. Нам нужно оставить на стеке параметр а, а с параметрами b c d поработать. Мы пишем определение Код: : proba /[312M3m'1 ; что эквивалентно Код: : proba { b c d } b c MAX d MIN ; После исполнения слова proba на стеке останется два параметра Код: a и результат от Код: b c MAX d MIN Для управления стеком при компиляции используются стековые эффекты входящих в определение через двоеточие слов. Это технологический прием. Каждое слово форта имеет стековый эффект - величина на которую слово меняет глубину стека. Зная исходное состояние стека и стековые эффекты последовательно выполняемых слов, можно вычислять положение ячеек стека во время компиляции кода определения. Сложности при компиляции возникают для ветвлений, циклов, слов типа EXECUTE, LAMBDA{ и тому подобных. Для циклов я ввел правило - стековый эффект внутри цикла должен быть нулевым(аналогия со стеком возвратов). Для ветвлений ввел массив трасс ветвления, в который вписываются вычисляемые стековые эффекты каждой трассы. Для EXECUTE нужно менять структуру словарной статьи - вводить туда значение стекового эффекта (сейчас я привязку слов к их стековым эффектам реализовал в обход словарей). Пока такие слова ( типа EXECUTE) не использую. Немного оптимизировал код определений через двоеточие в части сокращения числа перестановок указателя стека. Убрал слово DUP как лишнее, так как вместо него можно просто написать номер верхней ячейки. С DROP такое не проходит, хотя запись, например ]3, означает, что если в стеке было 4 параметра, останется 3 нижних, верхнее удалится. Таким образом DROP тоже можно исключить. Вот еще некоторые соображения на примере: Код: \ площадь треугольника по Герону : S3 { a b c \ p } a b + c + 2 / TO p p a - p b - * p c - * p * sqrt ; SEE S3
: s3 /[312+3+(2)/41-42-*43-*4*q'1 ; SEE s3
: TST 100 0 DO 3 4 5 S3 DROP LOOP ; TIME : tst 100 0 DO 3 4 5 s3 DROP LOOP ; time
CODE S3 621623 8945FC MOV FC [EBP] , EAX 621626 B80C000000 MOV EAX , # C 62162B 8D6DFC LEA EBP , FC [EBP] 62162E E8B11AF3FF CALL 5530E4 ( DRMOVE ) 621633 8945FC MOV FC [EBP] , EAX 621636 B801000000 MOV EAX , # 1 62163B 8D6DFC LEA EBP , FC [EBP] 62163E E8DD1BF3FF CALL 553220 ( (RALLOT) ) 621643 6810000000 PUSH , # 10 621648 6868325500 PUSH , # 553268 62164D 8945FC MOV FC [EBP] , EAX 621650 8B442414 MOV EAX , 14 [ESP] 621654 03442410 ADD EAX , 10 [ESP] 621658 0344240C ADD EAX , C [ESP] 62165C B902000000 MOV ECX , # 2 621661 99 CDQ 621662 F7F9 IDIV ECX 621664 89442408 MOV 8 [ESP] , EAX 621668 2B442414 SUB EAX , 14 [ESP] 62166C 8945F8 MOV F8 [EBP] , EAX 62166F 8B442408 MOV EAX , 8 [ESP] 621673 2B442410 SUB EAX , 10 [ESP] 621677 F76DF8 IMUL F8 [EBP] 62167A 8945F8 MOV F8 [EBP] , EAX 62167D 8B442408 MOV EAX , 8 [ESP] 621681 2B44240C SUB EAX , C [ESP] 621685 F76DF8 IMUL F8 [EBP] 621688 8945F8 MOV F8 [EBP] , EAX 62168B 8B442408 MOV EAX , 8 [ESP] 62168F F76DF8 IMUL F8 [EBP] 621692 8D6DFC LEA EBP , FC [EBP] 621695 E88D57FFFF CALL 616E27 ( sqrt ) 62169A C3 RET NEAR END-CODE ( 120 bytes, 33 instructions )
CODE s3 6216AB 8945FC MOV FC [EBP] , EAX 6216AE 8B4504 MOV EAX , 4 [EBP] 6216B1 034500 ADD EAX , 0 [EBP] 6216B4 0345FC ADD EAX , FC [EBP] 6216B7 8945F8 MOV F8 [EBP] , EAX 6216BA B802000000 MOV EAX , # 2 6216BF 8BC8 MOV ECX , EAX 6216C1 8B45F8 MOV EAX , F8 [EBP] 6216C4 99 CDQ 6216C5 F7F9 IDIV ECX 6216C7 8945F8 MOV F8 [EBP] , EAX 6216CA 2B4504 SUB EAX , 4 [EBP] 6216CD 8945F4 MOV F4 [EBP] , EAX 6216D0 8B45F8 MOV EAX , F8 [EBP] 6216D3 2B4500 SUB EAX , 0 [EBP] 6216D6 F76DF4 IMUL F4 [EBP] 6216D9 8945F4 MOV F4 [EBP] , EAX 6216DC 8B45F8 MOV EAX , F8 [EBP] 6216DF 2B45FC SUB EAX , FC [EBP] 6216E2 F76DF4 IMUL F4 [EBP] 6216E5 F76DF8 IMUL F8 [EBP] 6216E8 8D6DF8 LEA EBP , F8 [EBP] 6216EB E83757FFFF CALL 616E27 ( sqrt ) 6216F0 8D6D10 LEA EBP , 10 [EBP] 6216F3 C3 RET NEAR END-CODE ( 73 bytes, 25 instructions )
2836 ns ( время TST) 1274 ns ( время tst) Вычисление на стеке в итоге помещает результат в конкретную ячейку, в качестве имени которой в дальнейших вычислениях используется номер этой ячейки. Необходимости в явном присвоении (как для локальных переменных в SPF - см. пример выше ) нет, что дополнительно повышает эффективность кода. Еще кое-что: Использование номеров ячеек в качестве имен локальных переменных вполне годится, потому, что внутри определения локальных переменных немного и наделять их каким особым смыслом нет необходимости. PS. С Новым Годом!
[quote="Victor__v"]Как понимаю, Вы закидываете часть переменных выше вершины стека. Но как происходит контроль измерения глубины? При изменении этого самого стека?[/quote] Ничего никуда не закидывается. В начале манипулятора просто отмечается с каким количеством верхних параметров на стеке будет работать данный манипулятор. Вот на стеке находятся 4 параметра: a b c d. Нам нужно оставить на стеке параметр а, а с параметрами b c d поработать. Мы пишем определение [code]: proba /[312M3m'1 ;[/code] что эквивалентно [code]: proba { b c d } b c MAX d MIN ; [/code] После исполнения слова proba на стеке останется два параметра [code]a[/code] и результат от [code]b c MAX d MIN[/code] Для управления стеком при компиляции используются стековые эффекты входящих в определение через двоеточие слов. Это технологический прием. Каждое слово форта имеет стековый эффект - величина на которую слово меняет глубину стека. Зная исходное состояние стека и стековые эффекты последовательно выполняемых слов, можно вычислять положение ячеек стека во время компиляции кода определения. Сложности при компиляции возникают для ветвлений, циклов, слов типа EXECUTE, LAMBDA{ и тому подобных. Для циклов я ввел правило - стековый эффект внутри цикла должен быть нулевым(аналогия со стеком возвратов). Для ветвлений ввел массив трасс ветвления, в который вписываются вычисляемые стековые эффекты каждой трассы. Для EXECUTE нужно менять структуру словарной статьи - вводить туда значение стекового эффекта (сейчас я привязку слов к их стековым эффектам реализовал в обход словарей). Пока такие слова ( типа EXECUTE) не использую.
Немного оптимизировал код определений через двоеточие в части сокращения числа перестановок указателя стека. Убрал слово DUP как лишнее, так как вместо него можно просто написать номер верхней ячейки. С DROP такое не проходит, хотя запись, например ]3, означает, что если в стеке было 4 параметра, останется 3 нижних, верхнее удалится. Таким образом DROP тоже можно исключить.
Вот еще некоторые соображения на примере: [code]\ площадь треугольника по Герону : S3 { a b c \ p } a b + c + 2 / TO p p a - p b - * p c - * p * sqrt ; SEE S3
: s3 /[312+3+(2)/41-42-*43-*4*q'1 ; SEE s3
: TST 100 0 DO 3 4 5 S3 DROP LOOP ; TIME : tst 100 0 DO 3 4 5 s3 DROP LOOP ; time
CODE S3 621623 8945FC MOV FC [EBP] , EAX 621626 B80C000000 MOV EAX , # C 62162B 8D6DFC LEA EBP , FC [EBP] 62162E E8B11AF3FF CALL 5530E4 ( DRMOVE ) 621633 8945FC MOV FC [EBP] , EAX 621636 B801000000 MOV EAX , # 1 62163B 8D6DFC LEA EBP , FC [EBP] 62163E E8DD1BF3FF CALL 553220 ( (RALLOT) ) 621643 6810000000 PUSH , # 10 621648 6868325500 PUSH , # 553268 62164D 8945FC MOV FC [EBP] , EAX 621650 8B442414 MOV EAX , 14 [ESP] 621654 03442410 ADD EAX , 10 [ESP] 621658 0344240C ADD EAX , C [ESP] 62165C B902000000 MOV ECX , # 2 621661 99 CDQ 621662 F7F9 IDIV ECX 621664 89442408 MOV 8 [ESP] , EAX 621668 2B442414 SUB EAX , 14 [ESP] 62166C 8945F8 MOV F8 [EBP] , EAX 62166F 8B442408 MOV EAX , 8 [ESP] 621673 2B442410 SUB EAX , 10 [ESP] 621677 F76DF8 IMUL F8 [EBP] 62167A 8945F8 MOV F8 [EBP] , EAX 62167D 8B442408 MOV EAX , 8 [ESP] 621681 2B44240C SUB EAX , C [ESP] 621685 F76DF8 IMUL F8 [EBP] 621688 8945F8 MOV F8 [EBP] , EAX 62168B 8B442408 MOV EAX , 8 [ESP] 62168F F76DF8 IMUL F8 [EBP] 621692 8D6DFC LEA EBP , FC [EBP] 621695 E88D57FFFF CALL 616E27 ( sqrt ) 62169A C3 RET NEAR END-CODE ( 120 bytes, 33 instructions )
CODE s3 6216AB 8945FC MOV FC [EBP] , EAX 6216AE 8B4504 MOV EAX , 4 [EBP] 6216B1 034500 ADD EAX , 0 [EBP] 6216B4 0345FC ADD EAX , FC [EBP] 6216B7 8945F8 MOV F8 [EBP] , EAX 6216BA B802000000 MOV EAX , # 2 6216BF 8BC8 MOV ECX , EAX 6216C1 8B45F8 MOV EAX , F8 [EBP] 6216C4 99 CDQ 6216C5 F7F9 IDIV ECX 6216C7 8945F8 MOV F8 [EBP] , EAX 6216CA 2B4504 SUB EAX , 4 [EBP] 6216CD 8945F4 MOV F4 [EBP] , EAX 6216D0 8B45F8 MOV EAX , F8 [EBP] 6216D3 2B4500 SUB EAX , 0 [EBP] 6216D6 F76DF4 IMUL F4 [EBP] 6216D9 8945F4 MOV F4 [EBP] , EAX 6216DC 8B45F8 MOV EAX , F8 [EBP] 6216DF 2B45FC SUB EAX , FC [EBP] 6216E2 F76DF4 IMUL F4 [EBP] 6216E5 F76DF8 IMUL F8 [EBP] 6216E8 8D6DF8 LEA EBP , F8 [EBP] 6216EB E83757FFFF CALL 616E27 ( sqrt ) 6216F0 8D6D10 LEA EBP , 10 [EBP] 6216F3 C3 RET NEAR END-CODE ( 73 bytes, 25 instructions )
2836 ns ( время TST) 1274 ns ( время tst)[/code]
Вычисление на стеке в итоге помещает результат в конкретную ячейку, в качестве имени которой в дальнейших вычислениях используется номер этой ячейки. Необходимости в явном присвоении (как для локальных переменных в SPF - см. пример выше ) нет, что дополнительно повышает эффективность кода. Еще кое-что: Использование номеров ячеек в качестве имен локальных переменных вполне годится, потому, что внутри определения локальных переменных немного и наделять их каким особым смыслом нет необходимости. PS. С Новым Годом!
|
|
|
 |
Добавлено: Сб янв 01, 2022 17:29 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Еще один способ работы с параметрами на стеке |
 |
|
Как понимаю, Вы закидываете часть переменных выше вершины стека. Но как происходит контроль измерения глубины? При изменении этого самого стека?
Как понимаю, Вы закидываете часть переменных выше вершины стека. Но как происходит контроль измерения глубины? При изменении этого самого стека?
|
|
|
 |
Добавлено: Вт май 18, 2021 14:15 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Еще один способ работы с параметрами на стеке |
 |
|
Использовал доп. словарь. Вход в словарь (не_Forth) с помощью другой формы определения слова через двоеточие. Выход в словарь Forth по закрывающему символу ';', переопределенному в словаре не_Forth. Словарь поэтому практически не отсвечивает. Код: S+: | a1 u1 a2 u2 | u1 u2 + DUP ALLOC | u a | a1 a u1 MOVE a2 a u1 + u2 MOVE TO a1 nNIP u1 ; SEE S+ CR S" alfa ." S" .. omega" s+ TYPE
: s+ { a1 u1 a2 u2 \ a u } u1 u2 + DUP TO u ALLOCATE THROW TO a a1 a u1 MOVE a2 a u1 + u2 MOVE a u ; SEE s+ CR S" alfa ." S" .. omega" s+ TYPE лог Код: CODE S+ 620577 8945FC MOV FC [EBP] , EAX 62057A 034504 ADD EAX , 4 [EBP] 62057D 8D6DFC LEA EBP , FC [EBP] 620580 8945FC MOV FC [EBP] , EAX 620583 8D6DFC LEA EBP , FC [EBP] 620586 E8AC4DFFFF CALL 615337 ( hAlloc ) 62058B 8945FC MOV FC [EBP] , EAX 62058E 8B4510 MOV EAX , 10 [EBP] 620591 8945F8 MOV F8 [EBP] , EAX 620594 8B45FC MOV EAX , FC [EBP] 620597 8945F4 MOV F4 [EBP] , EAX 62059A 8B450C MOV EAX , C [EBP] 62059D 8D6DF4 LEA EBP , F4 [EBP] 6205A0 E8DF37F3FF CALL 553D84 ( MOVE ) 6205A5 8945FC MOV FC [EBP] , EAX 6205A8 8B4508 MOV EAX , 8 [EBP] 6205AB 8945F8 MOV F8 [EBP] , EAX 6205AE 8B45FC MOV EAX , FC [EBP] 6205B1 8D6DF8 LEA EBP , F8 [EBP] 6205B4 034514 ADD EAX , 14 [EBP] 6205B7 8945FC MOV FC [EBP] , EAX 6205BA 8B450C MOV EAX , C [EBP] 6205BD 8D6DFC LEA EBP , FC [EBP] 6205C0 E8BF37F3FF CALL 553D84 ( MOVE ) 6205C5 894510 MOV 10 [EBP] , EAX 6205C8 8B4500 MOV EAX , 0 [EBP] 6205CB 8D6D10 LEA EBP , 10 [EBP] 6205CE C3 RET NEAR END-CODE ( 88 bytes, 28 instructions )
alfa ... omega
CODE s+ 6205DF 8945FC MOV FC [EBP] , EAX 6205E2 B810000000 MOV EAX , # 10 6205E7 8D6DFC LEA EBP , FC [EBP] 6205EA E8F92AF3FF CALL 5530E8 ( DRMOVE ) 6205EF 8945FC MOV FC [EBP] , EAX 6205F2 B802000000 MOV EAX , # 2 6205F7 8D6DFC LEA EBP , FC [EBP] 6205FA E8252CF3FF CALL 553224 ( (RALLOT) ) 6205FF 6818000000 PUSH , # 18 620604 686C325500 PUSH , # 55326C 620609 8945FC MOV FC [EBP] , EAX 62060C 8B442418 MOV EAX , 18 [ESP] 620610 03442410 ADD EAX , 10 [ESP] 620614 8945F8 MOV F8 [EBP] , EAX 620617 89442408 MOV 8 [ESP] , EAX 62061B 8B45F8 MOV EAX , F8 [EBP] 62061E 8D6DFC LEA EBP , FC [EBP] 620621 E87649F3FF CALL 554F9C ( ALLOCATE ) 620626 E8894AF3FF CALL 5550B4 ( THROW ) 62062B 8944240C MOV C [ESP] , EAX 62062F 8B44241C MOV EAX , 1C [ESP] 620633 8945FC MOV FC [EBP] , EAX 620636 8B44240C MOV EAX , C [ESP] 62063A 8945F8 MOV F8 [EBP] , EAX 62063D 8B442418 MOV EAX , 18 [ESP] 620641 8D6DF8 LEA EBP , F8 [EBP] 620644 E83B37F3FF CALL 553D84 ( MOVE ) 620649 8945FC MOV FC [EBP] , EAX 62064C 8B442414 MOV EAX , 14 [ESP] 620650 8945F8 MOV F8 [EBP] , EAX 620653 8B44240C MOV EAX , C [ESP] 620657 03442418 ADD EAX , 18 [ESP] 62065B 8945F4 MOV F4 [EBP] , EAX 62065E 8B442410 MOV EAX , 10 [ESP] 620662 8D6DF4 LEA EBP , F4 [EBP] 620665 E81A37F3FF CALL 553D84 ( MOVE ) 62066A 8945FC MOV FC [EBP] , EAX 62066D 8B44240C MOV EAX , C [ESP] 620671 8945F8 MOV F8 [EBP] , EAX 620674 8B442408 MOV EAX , 8 [ESP] 620678 8D6DF8 LEA EBP , F8 [EBP] 62067B C3 RET NEAR END-CODE ( 157 bytes, 42 instructions )
alfa ... omega Ps. Увеличив число команд виртуальной форт-машины, и поддержав прозрачный синтаксис локальных переменных ( на самом деле использование стека в стандартном Форте это и есть оперирование локальными переменными пусть и неявно заданными) можно получить эффективность кода не хуже чем у форта с оптимизатором, при этом практически исключив инструментальный динамический контекст.
Использовал доп. словарь. Вход в словарь (не_Forth) с помощью другой формы определения слова через двоеточие. Выход в словарь Forth по закрывающему символу ';', переопределенному в словаре не_Forth. Словарь поэтому практически не отсвечивает.
[code]S+: | a1 u1 a2 u2 | u1 u2 + DUP ALLOC | u a | a1 a u1 MOVE a2 a u1 + u2 MOVE TO a1 nNIP u1 ; SEE S+ CR S" alfa ." S" .. omega" s+ TYPE
: s+ { a1 u1 a2 u2 \ a u } u1 u2 + DUP TO u ALLOCATE THROW TO a a1 a u1 MOVE a2 a u1 + u2 MOVE a u ; SEE s+ CR S" alfa ." S" .. omega" s+ TYPE[/code] лог [code]CODE S+ 620577 8945FC MOV FC [EBP] , EAX 62057A 034504 ADD EAX , 4 [EBP] 62057D 8D6DFC LEA EBP , FC [EBP] 620580 8945FC MOV FC [EBP] , EAX 620583 8D6DFC LEA EBP , FC [EBP] 620586 E8AC4DFFFF CALL 615337 ( hAlloc ) 62058B 8945FC MOV FC [EBP] , EAX 62058E 8B4510 MOV EAX , 10 [EBP] 620591 8945F8 MOV F8 [EBP] , EAX 620594 8B45FC MOV EAX , FC [EBP] 620597 8945F4 MOV F4 [EBP] , EAX 62059A 8B450C MOV EAX , C [EBP] 62059D 8D6DF4 LEA EBP , F4 [EBP] 6205A0 E8DF37F3FF CALL 553D84 ( MOVE ) 6205A5 8945FC MOV FC [EBP] , EAX 6205A8 8B4508 MOV EAX , 8 [EBP] 6205AB 8945F8 MOV F8 [EBP] , EAX 6205AE 8B45FC MOV EAX , FC [EBP] 6205B1 8D6DF8 LEA EBP , F8 [EBP] 6205B4 034514 ADD EAX , 14 [EBP] 6205B7 8945FC MOV FC [EBP] , EAX 6205BA 8B450C MOV EAX , C [EBP] 6205BD 8D6DFC LEA EBP , FC [EBP] 6205C0 E8BF37F3FF CALL 553D84 ( MOVE ) 6205C5 894510 MOV 10 [EBP] , EAX 6205C8 8B4500 MOV EAX , 0 [EBP] 6205CB 8D6D10 LEA EBP , 10 [EBP] 6205CE C3 RET NEAR END-CODE ( 88 bytes, 28 instructions )
alfa ... omega
CODE s+ 6205DF 8945FC MOV FC [EBP] , EAX 6205E2 B810000000 MOV EAX , # 10 6205E7 8D6DFC LEA EBP , FC [EBP] 6205EA E8F92AF3FF CALL 5530E8 ( DRMOVE ) 6205EF 8945FC MOV FC [EBP] , EAX 6205F2 B802000000 MOV EAX , # 2 6205F7 8D6DFC LEA EBP , FC [EBP] 6205FA E8252CF3FF CALL 553224 ( (RALLOT) ) 6205FF 6818000000 PUSH , # 18 620604 686C325500 PUSH , # 55326C 620609 8945FC MOV FC [EBP] , EAX 62060C 8B442418 MOV EAX , 18 [ESP] 620610 03442410 ADD EAX , 10 [ESP] 620614 8945F8 MOV F8 [EBP] , EAX 620617 89442408 MOV 8 [ESP] , EAX 62061B 8B45F8 MOV EAX , F8 [EBP] 62061E 8D6DFC LEA EBP , FC [EBP] 620621 E87649F3FF CALL 554F9C ( ALLOCATE ) 620626 E8894AF3FF CALL 5550B4 ( THROW ) 62062B 8944240C MOV C [ESP] , EAX 62062F 8B44241C MOV EAX , 1C [ESP] 620633 8945FC MOV FC [EBP] , EAX 620636 8B44240C MOV EAX , C [ESP] 62063A 8945F8 MOV F8 [EBP] , EAX 62063D 8B442418 MOV EAX , 18 [ESP] 620641 8D6DF8 LEA EBP , F8 [EBP] 620644 E83B37F3FF CALL 553D84 ( MOVE ) 620649 8945FC MOV FC [EBP] , EAX 62064C 8B442414 MOV EAX , 14 [ESP] 620650 8945F8 MOV F8 [EBP] , EAX 620653 8B44240C MOV EAX , C [ESP] 620657 03442418 ADD EAX , 18 [ESP] 62065B 8945F4 MOV F4 [EBP] , EAX 62065E 8B442410 MOV EAX , 10 [ESP] 620662 8D6DF4 LEA EBP , F4 [EBP] 620665 E81A37F3FF CALL 553D84 ( MOVE ) 62066A 8945FC MOV FC [EBP] , EAX 62066D 8B44240C MOV EAX , C [ESP] 620671 8945F8 MOV F8 [EBP] , EAX 620674 8B442408 MOV EAX , 8 [ESP] 620678 8D6DF8 LEA EBP , F8 [EBP] 62067B C3 RET NEAR END-CODE ( 157 bytes, 42 instructions )
alfa ... omega[/code]
Ps. Увеличив число команд виртуальной форт-машины, и поддержав прозрачный синтаксис локальных переменных ( на самом деле использование стека в стандартном Форте это и есть оперирование локальными переменными пусть и неявно заданными) можно получить эффективность кода не хуже чем у форта с оптимизатором, при этом практически исключив инструментальный динамический контекст.
|
|
|
 |
Добавлено: Сб май 15, 2021 23:53 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Еще один способ работы с параметрами на стеке |
 |
|
Наращивание возможностей транспилятора с параллельным изменением синтаксиса Код: \ Конкатенация строк в хипе : S+ | a1 u1 a2 u2 | u1 u2 s+ dup halloc | us as | a1 as u1 move a2 as u1 s+ u2 move IS a1 nNIP u1 ; SEE S+ CR S" 12 " S" ab" S+ TYPE ЛОГ Код: [424+dh162V362+4V:1'N2 \ выражение S+ на первичном языке b 2Ooo 3o 2 O1o: N
CODE S+ 62072F 8945FC MOV FC [EBP] , EAX 620732 034504 ADD EAX , 4 [EBP] 620735 8D6DFC LEA EBP , FC [EBP] 620738 8945FC MOV FC [EBP] , EAX 62073B 8D6DFC LEA EBP , FC [EBP] 62073E E8A84CFFFF CALL 6153EB ( hAlloc ) 620743 8945FC MOV FC [EBP] , EAX 620746 8B4510 MOV EAX , 10 [EBP] 620749 8945F8 MOV F8 [EBP] , EAX 62074C 8B45FC MOV EAX , FC [EBP] 62074F 8945F4 MOV F4 [EBP] , EAX 620752 8B450C MOV EAX , C [EBP] 620755 8D6DF4 LEA EBP , F4 [EBP] 620758 E82736F3FF CALL 553D84 ( MOVE ) 62075D 8945FC MOV FC [EBP] , EAX 620760 8B4508 MOV EAX , 8 [EBP] 620763 8945F8 MOV F8 [EBP] , EAX 620766 8B45FC MOV EAX , FC [EBP] 620769 8D6DF8 LEA EBP , F8 [EBP] 62076C 034514 ADD EAX , 14 [EBP] 62076F 8945FC MOV FC [EBP] , EAX 620772 8B450C MOV EAX , C [EBP] 620775 8D6DFC LEA EBP , FC [EBP] 620778 E80736F3FF CALL 553D84 ( MOVE ) 62077D 894510 MOV 10 [EBP] , EAX 620780 8B4500 MOV EAX , 0 [EBP] 620783 8D6D10 LEA EBP , 10 [EBP] 620786 C3 RET NEAR END-CODE ( 88 bytes, 28 instructions )
12 ab PS. В основном процесс транспиляции освоен, остались экстенсивные дополнения.
Наращивание возможностей транспилятора с параллельным изменением синтаксиса [code]\ Конкатенация строк в хипе : S+ | a1 u1 a2 u2 | u1 u2 s+ dup halloc | us as | a1 as u1 move a2 as u1 s+ u2 move IS a1 nNIP u1 ; SEE S+ CR S" 12 " S" ab" S+ TYPE[/code]
ЛОГ [code][424+dh162V362+4V:1'N2 \ выражение S+ на первичном языке b 2Ooo 3o 2 O1o: N
CODE S+ 62072F 8945FC MOV FC [EBP] , EAX 620732 034504 ADD EAX , 4 [EBP] 620735 8D6DFC LEA EBP , FC [EBP] 620738 8945FC MOV FC [EBP] , EAX 62073B 8D6DFC LEA EBP , FC [EBP] 62073E E8A84CFFFF CALL 6153EB ( hAlloc ) 620743 8945FC MOV FC [EBP] , EAX 620746 8B4510 MOV EAX , 10 [EBP] 620749 8945F8 MOV F8 [EBP] , EAX 62074C 8B45FC MOV EAX , FC [EBP] 62074F 8945F4 MOV F4 [EBP] , EAX 620752 8B450C MOV EAX , C [EBP] 620755 8D6DF4 LEA EBP , F4 [EBP] 620758 E82736F3FF CALL 553D84 ( MOVE ) 62075D 8945FC MOV FC [EBP] , EAX 620760 8B4508 MOV EAX , 8 [EBP] 620763 8945F8 MOV F8 [EBP] , EAX 620766 8B45FC MOV EAX , FC [EBP] 620769 8D6DF8 LEA EBP , F8 [EBP] 62076C 034514 ADD EAX , 14 [EBP] 62076F 8945FC MOV FC [EBP] , EAX 620772 8B450C MOV EAX , C [EBP] 620775 8D6DFC LEA EBP , FC [EBP] 620778 E80736F3FF CALL 553D84 ( MOVE ) 62077D 894510 MOV 10 [EBP] , EAX 620780 8B4500 MOV EAX , 0 [EBP] 620783 8D6D10 LEA EBP , 10 [EBP] 620786 C3 RET NEAR END-CODE ( 88 bytes, 28 instructions )
12 ab[/code] PS. В основном процесс транспиляции освоен, остались экстенсивные дополнения.
|
|
|
 |
Добавлено: Чт май 13, 2021 00:58 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Еще один способ работы с параметрами на стеке |
 |
|
Версия простейшего транспилятора Код: CREATE VocPar 2000 ALLOT 0 VALUE dvp \ словарь имен параметров CREATE StrOut 1000 ALLOT 0 VALUE dso \ выходная строка на первичном языке
I: [[ { \ cw a u } BEGIN NextWord 2DUP TO u TO a S" ]]" COMPARE IF a VocPar dvp + u MOVE dvp u + 1+ TO dvp cw 1+ TO cw cw '0' + VocPar dvp + C! dvp 2+ TO dvp 0 ELSE 1 THEN UNTIL S" /[" StrOut SWAP MOVE cw '0' + StrOut 2 + C! dso 3 + TO dso ; : NOTFOUND { a u } VocPar 2000 a u SEARCH IF DROP u + 1+ C@ StrOut dso + C! dso 1+ TO dso ELSE 2DROP a u NOTFOUND EXIT THEN ; I: em StrOut dso EVALUATE ; I: m; ` em StrOut 1000 ERASE ` ; ; Проверка Код: : s1 /[4321441 ; SEE s1 11 22 33 44 t[ s1 ]t : s2 [[ a1 u1 a2 u2 ]] a2 u1 a1 u2 u2 a1 m; SEE s2 11 22 33 44 t[ s2 ]t ЛОГ Код: [4321441 b 6
CODE s1 6201B7 8945FC MOV FC [EBP] , EAX 6201BA 8B4500 MOV EAX , 0 [EBP] 6201BD 8945F8 MOV F8 [EBP] , EAX 6201C0 8B4504 MOV EAX , 4 [EBP] 6201C3 8945F4 MOV F4 [EBP] , EAX 6201C6 8B4508 MOV EAX , 8 [EBP] 6201C9 8945F0 MOV F0 [EBP] , EAX 6201CC 8B45FC MOV EAX , FC [EBP] 6201CF 8945EC MOV EC [EBP] , EAX 6201D2 8B45FC MOV EAX , FC [EBP] 6201D5 8945E8 MOV E8 [EBP] , EAX 6201D8 8B4508 MOV EAX , 8 [EBP] 6201DB 8D6DE8 LEA EBP , E8 [EBP] 6201DE C3 RET NEAR END-CODE ( 40 bytes, 14 instructions )
11 22 33 44 11 22 33 44 33 22 11 44 44 11
[4321441 b 6
CODE s2 6201EF 8945FC MOV FC [EBP] , EAX 6201F2 8B4500 MOV EAX , 0 [EBP] 6201F5 8945F8 MOV F8 [EBP] , EAX 6201F8 8B4504 MOV EAX , 4 [EBP] 6201FB 8945F4 MOV F4 [EBP] , EAX 6201FE 8B4508 MOV EAX , 8 [EBP] 620201 8945F0 MOV F0 [EBP] , EAX 620204 8B45FC MOV EAX , FC [EBP] 620207 8945EC MOV EC [EBP] , EAX 62020A 8B45FC MOV EAX , FC [EBP] 62020D 8945E8 MOV E8 [EBP] , EAX 620210 8B4508 MOV EAX , 8 [EBP] 620213 8D6DE8 LEA EBP , E8 [EBP] 620216 C3 RET NEAR END-CODE ( 40 bytes, 14 instructions )
11 22 33 44 11 22 33 44 33 22 11 44 44 11 PS. 100% точный перевод на первичный язык. Это конечно лишь часть транспилятора.
Версия простейшего транспилятора [code]CREATE VocPar 2000 ALLOT 0 VALUE dvp \ словарь имен параметров CREATE StrOut 1000 ALLOT 0 VALUE dso \ выходная строка на первичном языке
I: [[ { \ cw a u } BEGIN NextWord 2DUP TO u TO a S" ]]" COMPARE IF a VocPar dvp + u MOVE dvp u + 1+ TO dvp cw 1+ TO cw cw '0' + VocPar dvp + C! dvp 2+ TO dvp 0 ELSE 1 THEN UNTIL S" /[" StrOut SWAP MOVE cw '0' + StrOut 2 + C! dso 3 + TO dso ; : NOTFOUND { a u } VocPar 2000 a u SEARCH IF DROP u + 1+ C@ StrOut dso + C! dso 1+ TO dso ELSE 2DROP a u NOTFOUND EXIT THEN ; I: em StrOut dso EVALUATE ; I: m; ` em StrOut 1000 ERASE ` ; ;[/code] Проверка [code]: s1 /[4321441 ; SEE s1 11 22 33 44 t[ s1 ]t : s2 [[ a1 u1 a2 u2 ]] a2 u1 a1 u2 u2 a1 m; SEE s2 11 22 33 44 t[ s2 ]t[/code]
ЛОГ [code][4321441 b 6
CODE s1 6201B7 8945FC MOV FC [EBP] , EAX 6201BA 8B4500 MOV EAX , 0 [EBP] 6201BD 8945F8 MOV F8 [EBP] , EAX 6201C0 8B4504 MOV EAX , 4 [EBP] 6201C3 8945F4 MOV F4 [EBP] , EAX 6201C6 8B4508 MOV EAX , 8 [EBP] 6201C9 8945F0 MOV F0 [EBP] , EAX 6201CC 8B45FC MOV EAX , FC [EBP] 6201CF 8945EC MOV EC [EBP] , EAX 6201D2 8B45FC MOV EAX , FC [EBP] 6201D5 8945E8 MOV E8 [EBP] , EAX 6201D8 8B4508 MOV EAX , 8 [EBP] 6201DB 8D6DE8 LEA EBP , E8 [EBP] 6201DE C3 RET NEAR END-CODE ( 40 bytes, 14 instructions )
11 22 33 44 11 22 33 44 33 22 11 44 44 11
[4321441 b 6
CODE s2 6201EF 8945FC MOV FC [EBP] , EAX 6201F2 8B4500 MOV EAX , 0 [EBP] 6201F5 8945F8 MOV F8 [EBP] , EAX 6201F8 8B4504 MOV EAX , 4 [EBP] 6201FB 8945F4 MOV F4 [EBP] , EAX 6201FE 8B4508 MOV EAX , 8 [EBP] 620201 8945F0 MOV F0 [EBP] , EAX 620204 8B45FC MOV EAX , FC [EBP] 620207 8945EC MOV EC [EBP] , EAX 62020A 8B45FC MOV EAX , FC [EBP] 62020D 8945E8 MOV E8 [EBP] , EAX 620210 8B4508 MOV EAX , 8 [EBP] 620213 8D6DE8 LEA EBP , E8 [EBP] 620216 C3 RET NEAR END-CODE ( 40 bytes, 14 instructions )
11 22 33 44 11 22 33 44 33 22 11 44 44 11[/code] PS. 100% точный перевод на первичный язык. Это конечно лишь часть транспилятора.
|
|
|
 |
Добавлено: Ср май 12, 2021 01:08 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Еще один способ работы с параметрами на стеке |
 |
|
Ввел операторы между содержимым ячейки и непосредсвенно заданным операндом Результат всегда помещается в ячейку. Код: : t[ CR DEPTH .SN CR ; : ]t DEPTH .SN stack0 ; 1 TO OTL : pr1 /[31`2'+ ; SEE pr1 16 2 32 t[ pr1 ]t : pr2 /[33`2'- ; SEE pr2 16 2 32 t[ pr2 ]t : pr3 /[31`2'* ; SEE pr3 16 2 32 t[ pr3 ]t : pr4 /[33`2'/ ; SEE pr4 16 2 32 t[ pr4 ]t : pr5 /[31`2'% ; SEE pr5 16 2 32 t[ pr5 ]t : pr6 /[33`2'| ; SEE pr6 16 2 32 t[ pr6 ]t : pr7 /[31`2'& ; SEE pr7 16 2 32 t[ pr7 ]t : pr8 /[33`2'^ ; SEE pr8 16 2 32 t[ pr8 ]t : pr9 /[31`2'M ; SEE pr9 16 2 32 t[ pr9 ]t : prA /[33`2'm ; SEE prA 16 2 32 t[ prA ]t : prB /[31`2'l ; SEE prB 16 2 32 t[ prB ]t : prC /[33`2'r ; SEE prC 16 2 32 t[ prC ]t ЛОГ. Код: [31`2'+ b c_#_o
CODE pr1 61DCD7 83450402 ADD 4 [EBP] , # 2 61DCDB C3 RET NEAR END-CODE ( 5 bytes, 2 instructions )
16 2 32 18 2 32
[33`2'- b c_#_o
CODE pr2 61DCEF 8D40FE LEA EAX , FE [EAX] 61DCF2 C3 RET NEAR END-CODE ( 4 bytes, 2 instructions )
16 2 32 16 2 30
[31`2'* b c_#_o
CODE pr3 61DD03 695D0402000000 IMUL EBX , 4 [EBP] , # 2 61DD0A 895D04 MOV 4 [EBP] , EBX 61DD0D C3 RET NEAR END-CODE ( 11 bytes, 3 instructions )
16 2 32 32 2 32
[33`2'/ b c_#_o
CODE pr4 61DD1F C7C102000000 MOV ECX , # 2 61DD25 99 CDQ 61DD26 F7F9 IDIV ECX 61DD28 C3 RET NEAR END-CODE ( 10 bytes, 4 instructions )
16 2 32 16 2 16
[31`2'% b c_#_o
CODE pr5 61DD3B 8BD8 MOV EBX , EAX 61DD3D 8B4504 MOV EAX , 4 [EBP] 61DD40 C7C102000000 MOV ECX , # 2 61DD46 99 CDQ 61DD47 F7F9 IDIV ECX 61DD49 895504 MOV 4 [EBP] , EDX 61DD4C 8BC3 MOV EAX , EBX 61DD4E C3 RET NEAR END-CODE ( 20 bytes, 8 instructions )
16 2 32 0 2 32
[33`2'| b c_#_o
CODE pr6 61DD5F 81C802000000 OR EAX , # 2 61DD65 C3 RET NEAR END-CODE ( 7 bytes, 2 instructions )
16 2 32 16 2 34
[31`2'& b c_#_o
CODE pr7 61DD77 81650402000000 AND 4 [EBP] , # 2 61DD7E C3 RET NEAR END-CODE ( 8 bytes, 2 instructions )
16 2 32 0 2 32
[33`2'^ b c_#_o
CODE pr8 61DD8F 81F002000000 XOR EAX , # 2 61DD95 C3 RET NEAR END-CODE ( 7 bytes, 2 instructions )
16 2 32 16 2 34
[31`2'M b c_#_o
CODE pr9 61DDA7 C7C302000000 MOV EBX , # 2 61DDAD 395D04 CMP 4 [EBP] , EBX 61DDB0 0F4F5D04 CMOVG EBX , 4 [EBP] 61DDB4 895D04 MOV 4 [EBP] , EBX 61DDB7 C3 RET NEAR END-CODE ( 17 bytes, 5 instructions )
16 2 32 16 2 32
[33`2'm b c_#_o
CODE prA 61DDCB C7C202000000 MOV EDX , # 2 61DDD1 3BD0 CMP EDX , EAX 61DDD3 0F4CC2 CMOVL EAX , EDX 61DDD6 C3 RET NEAR END-CODE ( 12 bytes, 4 instructions )
16 2 32 16 2 2
[31`2'l b c_#_o
CODE prB 61DDE7 C1650402 SHL 4 [EBP] , 2 61DDEB C3 RET NEAR END-CODE ( 5 bytes, 2 instructions )
16 2 32 64 2 32
[33`2'r b c_#_o
CODE prC 61DDFF C1E802 SHR EAX , 2 61DE02 C3 RET NEAR END-CODE ( 4 bytes, 2 instructions )
16 2 32 16 2 8
PS. Кратко пройдусь по всему набору операторов (с - ячейка, # - непосредственное значение, o - оператор) с1с2o - результат на вершину стека с1с2'o - результат в ячейку с1 c#'o - результат в ячейку с ##o - результат на вершину стека co - результат на вершину стека( оператор между вершиной стека и ячейкой ) o - фортовские операторы с - содержимое ячейки на стек с1:c2 - пересылка из ячейки в ячейку :c - снять со стека в ячейку(':c - скопировать со стека в ячейку) есть еще операторы укорочения стека nDROP ( ]n ) и nNIP( 'Nn ) Несмотря на введение доп. операторов язык остается по прежнему стековым.
Ввел операторы между содержимым ячейки и непосредсвенно заданным операндом Результат всегда помещается в ячейку. [code]: t[ CR DEPTH .SN CR ; : ]t DEPTH .SN stack0 ; 1 TO OTL : pr1 /[31`2'+ ; SEE pr1 16 2 32 t[ pr1 ]t : pr2 /[33`2'- ; SEE pr2 16 2 32 t[ pr2 ]t : pr3 /[31`2'* ; SEE pr3 16 2 32 t[ pr3 ]t : pr4 /[33`2'/ ; SEE pr4 16 2 32 t[ pr4 ]t : pr5 /[31`2'% ; SEE pr5 16 2 32 t[ pr5 ]t : pr6 /[33`2'| ; SEE pr6 16 2 32 t[ pr6 ]t : pr7 /[31`2'& ; SEE pr7 16 2 32 t[ pr7 ]t : pr8 /[33`2'^ ; SEE pr8 16 2 32 t[ pr8 ]t : pr9 /[31`2'M ; SEE pr9 16 2 32 t[ pr9 ]t : prA /[33`2'm ; SEE prA 16 2 32 t[ prA ]t : prB /[31`2'l ; SEE prB 16 2 32 t[ prB ]t : prC /[33`2'r ; SEE prC 16 2 32 t[ prC ]t[/code]
ЛОГ. [code][31`2'+ b c_#_o
CODE pr1 61DCD7 83450402 ADD 4 [EBP] , # 2 61DCDB C3 RET NEAR END-CODE ( 5 bytes, 2 instructions )
16 2 32 18 2 32
[33`2'- b c_#_o
CODE pr2 61DCEF 8D40FE LEA EAX , FE [EAX] 61DCF2 C3 RET NEAR END-CODE ( 4 bytes, 2 instructions )
16 2 32 16 2 30
[31`2'* b c_#_o
CODE pr3 61DD03 695D0402000000 IMUL EBX , 4 [EBP] , # 2 61DD0A 895D04 MOV 4 [EBP] , EBX 61DD0D C3 RET NEAR END-CODE ( 11 bytes, 3 instructions )
16 2 32 32 2 32
[33`2'/ b c_#_o
CODE pr4 61DD1F C7C102000000 MOV ECX , # 2 61DD25 99 CDQ 61DD26 F7F9 IDIV ECX 61DD28 C3 RET NEAR END-CODE ( 10 bytes, 4 instructions )
16 2 32 16 2 16
[31`2'% b c_#_o
CODE pr5 61DD3B 8BD8 MOV EBX , EAX 61DD3D 8B4504 MOV EAX , 4 [EBP] 61DD40 C7C102000000 MOV ECX , # 2 61DD46 99 CDQ 61DD47 F7F9 IDIV ECX 61DD49 895504 MOV 4 [EBP] , EDX 61DD4C 8BC3 MOV EAX , EBX 61DD4E C3 RET NEAR END-CODE ( 20 bytes, 8 instructions )
16 2 32 0 2 32
[33`2'| b c_#_o
CODE pr6 61DD5F 81C802000000 OR EAX , # 2 61DD65 C3 RET NEAR END-CODE ( 7 bytes, 2 instructions )
16 2 32 16 2 34
[31`2'& b c_#_o
CODE pr7 61DD77 81650402000000 AND 4 [EBP] , # 2 61DD7E C3 RET NEAR END-CODE ( 8 bytes, 2 instructions )
16 2 32 0 2 32
[33`2'^ b c_#_o
CODE pr8 61DD8F 81F002000000 XOR EAX , # 2 61DD95 C3 RET NEAR END-CODE ( 7 bytes, 2 instructions )
16 2 32 16 2 34
[31`2'M b c_#_o
CODE pr9 61DDA7 C7C302000000 MOV EBX , # 2 61DDAD 395D04 CMP 4 [EBP] , EBX 61DDB0 0F4F5D04 CMOVG EBX , 4 [EBP] 61DDB4 895D04 MOV 4 [EBP] , EBX 61DDB7 C3 RET NEAR END-CODE ( 17 bytes, 5 instructions )
16 2 32 16 2 32
[33`2'm b c_#_o
CODE prA 61DDCB C7C202000000 MOV EDX , # 2 61DDD1 3BD0 CMP EDX , EAX 61DDD3 0F4CC2 CMOVL EAX , EDX 61DDD6 C3 RET NEAR END-CODE ( 12 bytes, 4 instructions )
16 2 32 16 2 2
[31`2'l b c_#_o
CODE prB 61DDE7 C1650402 SHL 4 [EBP] , 2 61DDEB C3 RET NEAR END-CODE ( 5 bytes, 2 instructions )
16 2 32 64 2 32
[33`2'r b c_#_o
CODE prC 61DDFF C1E802 SHR EAX , 2 61DE02 C3 RET NEAR END-CODE ( 4 bytes, 2 instructions )
16 2 32 16 2 8 [/code] PS. Кратко пройдусь по всему набору операторов (с - ячейка, # - непосредственное значение, o - оператор)
с1с2o - результат на вершину стека с1с2'o - результат в ячейку с1 c#'o - результат в ячейку с ##o - результат на вершину стека co - результат на вершину стека( оператор между вершиной стека и ячейкой ) o - фортовские операторы с - содержимое ячейки на стек с1:c2 - пересылка из ячейки в ячейку :c - снять со стека в ячейку(':c - скопировать со стека в ячейку) есть еще операторы укорочения стека nDROP ( ]n ) и nNIP( 'Nn ) Несмотря на введение доп. операторов язык остается по прежнему стековым.
|
|
|
 |
Добавлено: Вт май 04, 2021 00:55 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Еще один способ работы с параметрами на стеке |
 |
|
Ввел прямые операции между ячейками стека в общем случае минуя вершину стека. Форт-операторы идут как их подмножество с более коротким синтаксисом. Примеры реализации операторов + и - : Код: : s. DEPTH .SN stack0 ; 1 TO OTL : pr1 /[312'+ ; SEE pr1 1 2 3 pr1 s. : pr2 /[313'+ ; SEE pr2 1 2 3 pr2 s. : pr3 /[323'+ ; SEE pr3 1 2 3 pr3 s. : pr4 /[321'+ ; SEE pr4 1 2 3 pr4 s. : pr5 /[331'+ ; SEE pr5 1 2 3 pr5 s. : pr6 /[332'+ ; SEE pr6 1 2 3 pr6 s. : pr7 /[312'- ; SEE pr7 1 2 3 pr7 s. : pr8 /[313'- ; SEE pr8 1 2 3 pr8 s. : pr9 /[323'- ; SEE pr9 1 2 3 pr9 s. : prA /[321'- ; SEE prA 1 2 3 prA s. : prB /[331'- ; SEE prB 1 2 3 prB s. : prC /[332'- ; SEE prC 1 2 3 prC s. ЛОГ. Код: [312'+ b cc_o
CODE pr1 60C6BB 8B4D00 MOV ECX , 0 [EBP] 60C6BE 014D04 ADD 4 [EBP] , ECX 60C6C1 C3 RET NEAR END-CODE ( 7 bytes, 3 instructions ) 3 2 3
[313'+ b cc_o
CODE pr2 60C6D3 014504 ADD 4 [EBP] , EAX 60C6D6 C3 RET NEAR END-CODE ( 4 bytes, 2 instructions ) 4 2 3
[323'+ b cc_o
CODE pr3 60C6E7 014500 ADD 0 [EBP] , EAX 60C6EA C3 RET NEAR END-CODE ( 4 bytes, 2 instructions ) 1 5 3
[321'+ b cc_o
CODE pr4 60C6FB 8B4D04 MOV ECX , 4 [EBP] 60C6FE 014D00 ADD 0 [EBP] , ECX 60C701 C3 RET NEAR END-CODE ( 7 bytes, 3 instructions ) 1 3 3
[331'+ b cc_o
CODE pr5 60C713 034504 ADD EAX , 4 [EBP] 60C716 C3 RET NEAR END-CODE ( 4 bytes, 2 instructions ) 1 2 4
[332'+ b cc_o
CODE pr6 60C727 034500 ADD EAX , 0 [EBP] 60C72A C3 RET NEAR END-CODE ( 4 bytes, 2 instructions ) 1 2 5
[312'- b cc_o
CODE pr7 60C73B 8B4D00 MOV ECX , 0 [EBP] 60C73E 294D04 SUB 4 [EBP] , ECX 60C741 C3 RET NEAR END-CODE ( 7 bytes, 3 instructions ) 4294967295(-1) 2 3
[313'- b cc_o
CODE pr8 60C753 294504 SUB 4 [EBP] , EAX 60C756 C3 RET NEAR END-CODE ( 4 bytes, 2 instructions ) 4294967294(-2) 2 3
[323'- b cc_o
CODE pr9 60C767 294500 SUB 0 [EBP] , EAX 60C76A C3 RET NEAR END-CODE ( 4 bytes, 2 instructions ) 1 4294967295(-1) 3
[321'- b cc_o
CODE prA 60C77B 8B4D04 MOV ECX , 4 [EBP] 60C77E 294D00 SUB 0 [EBP] , ECX 60C781 C3 RET NEAR END-CODE ( 7 bytes, 3 instructions ) 1 1 3
[331'- b cc_o
CODE prB 60C793 2B4504 SUB EAX , 4 [EBP] 60C796 C3 RET NEAR END-CODE ( 4 bytes, 2 instructions ) 1 2 2
[332'- b cc_o
CODE prC 60C7A7 2B4500 SUB EAX , 0 [EBP] 60C7AA C3 RET NEAR END-CODE ( 4 bytes, 2 instructions ) 1 2 1 Ok
PS. Такие операторы нужны для работы с ячейками стека как с локальными переменными.
Ввел прямые операции между ячейками стека в общем случае минуя вершину стека. Форт-операторы идут как их подмножество с более коротким синтаксисом. Примеры реализации операторов + и - : [code]: s. DEPTH .SN stack0 ; 1 TO OTL : pr1 /[312'+ ; SEE pr1 1 2 3 pr1 s. : pr2 /[313'+ ; SEE pr2 1 2 3 pr2 s. : pr3 /[323'+ ; SEE pr3 1 2 3 pr3 s. : pr4 /[321'+ ; SEE pr4 1 2 3 pr4 s. : pr5 /[331'+ ; SEE pr5 1 2 3 pr5 s. : pr6 /[332'+ ; SEE pr6 1 2 3 pr6 s. : pr7 /[312'- ; SEE pr7 1 2 3 pr7 s. : pr8 /[313'- ; SEE pr8 1 2 3 pr8 s. : pr9 /[323'- ; SEE pr9 1 2 3 pr9 s. : prA /[321'- ; SEE prA 1 2 3 prA s. : prB /[331'- ; SEE prB 1 2 3 prB s. : prC /[332'- ; SEE prC 1 2 3 prC s.[/code]
ЛОГ. [code][312'+ b cc_o
CODE pr1 60C6BB 8B4D00 MOV ECX , 0 [EBP] 60C6BE 014D04 ADD 4 [EBP] , ECX 60C6C1 C3 RET NEAR END-CODE ( 7 bytes, 3 instructions ) 3 2 3
[313'+ b cc_o
CODE pr2 60C6D3 014504 ADD 4 [EBP] , EAX 60C6D6 C3 RET NEAR END-CODE ( 4 bytes, 2 instructions ) 4 2 3
[323'+ b cc_o
CODE pr3 60C6E7 014500 ADD 0 [EBP] , EAX 60C6EA C3 RET NEAR END-CODE ( 4 bytes, 2 instructions ) 1 5 3
[321'+ b cc_o
CODE pr4 60C6FB 8B4D04 MOV ECX , 4 [EBP] 60C6FE 014D00 ADD 0 [EBP] , ECX 60C701 C3 RET NEAR END-CODE ( 7 bytes, 3 instructions ) 1 3 3
[331'+ b cc_o
CODE pr5 60C713 034504 ADD EAX , 4 [EBP] 60C716 C3 RET NEAR END-CODE ( 4 bytes, 2 instructions ) 1 2 4
[332'+ b cc_o
CODE pr6 60C727 034500 ADD EAX , 0 [EBP] 60C72A C3 RET NEAR END-CODE ( 4 bytes, 2 instructions ) 1 2 5
[312'- b cc_o
CODE pr7 60C73B 8B4D00 MOV ECX , 0 [EBP] 60C73E 294D04 SUB 4 [EBP] , ECX 60C741 C3 RET NEAR END-CODE ( 7 bytes, 3 instructions ) 4294967295(-1) 2 3
[313'- b cc_o
CODE pr8 60C753 294504 SUB 4 [EBP] , EAX 60C756 C3 RET NEAR END-CODE ( 4 bytes, 2 instructions ) 4294967294(-2) 2 3
[323'- b cc_o
CODE pr9 60C767 294500 SUB 0 [EBP] , EAX 60C76A C3 RET NEAR END-CODE ( 4 bytes, 2 instructions ) 1 4294967295(-1) 3
[321'- b cc_o
CODE prA 60C77B 8B4D04 MOV ECX , 4 [EBP] 60C77E 294D00 SUB 0 [EBP] , ECX 60C781 C3 RET NEAR END-CODE ( 7 bytes, 3 instructions ) 1 1 3
[331'- b cc_o
CODE prB 60C793 2B4504 SUB EAX , 4 [EBP] 60C796 C3 RET NEAR END-CODE ( 4 bytes, 2 instructions ) 1 2 2
[332'- b cc_o
CODE prC 60C7A7 2B4500 SUB EAX , 0 [EBP] 60C7AA C3 RET NEAR END-CODE ( 4 bytes, 2 instructions ) 1 2 1 Ok [/code] PS. Такие операторы нужны для работы с ячейками стека как с локальными переменными.
|
|
|
 |
Добавлено: Пн апр 26, 2021 00:56 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Еще один способ работы с параметрами на стеке |
 |
|
Ввел поддержку операций над непосредственно заданными операндами Код: : tst /`5`4*`3-`A*`4/`5+`A* ; SEE tst tst : tst1 5 4 * 3 - 10 * 4 / 5 + 10 * ; SEE tst1 tst1
LOG Код: CODE tst 60C197 8945FC MOV FC [EBP] , EAX 60C19A B8D6010000 MOV EAX , # 1D6 60C19F 8D6DFC LEA EBP , FC [EBP] 60C1A2 C3 RET NEAR END-CODE ( 12 bytes, 4 instructions )
CODE tst1 60C1B7 8945FC MOV FC [EBP] , EAX 60C1BA B8AA000000 MOV EAX , # AA 60C1BF B904000000 MOV ECX , # 4 60C1C4 99 CDQ 60C1C5 F7F9 IDIV ECX 60C1C7 8D4005 LEA EAX , 5 [EAX] 60C1CA 69C00A000000 IMUL EAX , EAX , # A 60C1D0 8D6DFC LEA EBP , FC [EBP] 60C1D3 C3 RET NEAR END-CODE ( 29 bytes, 9 instructions )
Ok ( 470 470 ) PS Использовал прием модификации исходного текста во время компиляции, поэтому все вылилось в добавку двух строчек в текст транслятора.
Ввел поддержку операций над непосредственно заданными операндами [code]: tst /`5`4*`3-`A*`4/`5+`A* ; SEE tst tst : tst1 5 4 * 3 - 10 * 4 / 5 + 10 * ; SEE tst1 tst1 [/code] LOG [code]CODE tst 60C197 8945FC MOV FC [EBP] , EAX 60C19A B8D6010000 MOV EAX , # 1D6 60C19F 8D6DFC LEA EBP , FC [EBP] 60C1A2 C3 RET NEAR END-CODE ( 12 bytes, 4 instructions )
CODE tst1 60C1B7 8945FC MOV FC [EBP] , EAX 60C1BA B8AA000000 MOV EAX , # AA 60C1BF B904000000 MOV ECX , # 4 60C1C4 99 CDQ 60C1C5 F7F9 IDIV ECX 60C1C7 8D4005 LEA EAX , 5 [EAX] 60C1CA 69C00A000000 IMUL EAX , EAX , # A 60C1D0 8D6DFC LEA EBP , FC [EBP] 60C1D3 C3 RET NEAR END-CODE ( 29 bytes, 9 instructions )
Ok ( 470 470 )[/code] PS Использовал прием модификации исходного текста во время компиляции, поэтому все вылилось в добавку двух строчек в текст транслятора.
|
|
|
 |
Добавлено: Сб апр 17, 2021 16:16 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Еще один способ работы с параметрами на стеке |
 |
|
Ввел слова прямого изменения содержимого ячеек стека. Как правило такие ячейки используются как счетчики в циклах. Код: : d. CR DEPTH .SN S0 @ SP! ;
1 TO OTL \ вкл декомпилятор
\ примеры увеличения-уменьшения содержимого ячеек : tst /[4"1A'2F"32'41 ; SEE tst 10 20 30 40 tst d.
: tst1 /[2"13'25* ; SEE tst1 3 12 tst1 d. LOG Код: [4"1A'2F"32'41 \ (1c + 10) (2c - 15) (3c + 2) (4c - 1) b +c#-c#+c#-c#
CODE tst 60B133 8345080A ADD 8 [EBP] , # 10 60B137 836D040F SUB 4 [EBP] , # 15 60B13B 83450002 ADD 0 [EBP] , # 2 60B13F 8D40FF LEA EAX , FF [EAX] 60B142 C3 RET NEAR END-CODE ( 16 bytes, 5 instructions )
20 5 32 39
[2"13'25* b +c#-c#o
CODE tst1 60B153 83450003 ADD 0 [EBP] , # 3 60B157 8D40FB LEA EAX , FB [EAX] 60B15A F76D00 IMUL 0 [EBP] 60B15D 8D6D04 LEA EBP , 4 [EBP] 60B160 C3 RET NEAR END-CODE ( 14 bytes, 5 instructions )
42
PS. Синтаксис на данном этапе может меняться. В конечном итоге можно написать транспилятор для более удобного представления таких выражений, например аналогичных SPF-му виду для локальных переменных, только с возможностью многократного применения конструкций типа { a b c | d e f ... } и использования имен обычных слов форта. Сама текущая нотация будет первичным(промежуточным) языком.
Ввел слова прямого изменения содержимого ячеек стека. Как правило такие ячейки используются как счетчики в циклах. [code] : d. CR DEPTH .SN S0 @ SP! ;
1 TO OTL \ вкл декомпилятор
\ примеры увеличения-уменьшения содержимого ячеек : tst /[4"1A'2F"32'41 ; SEE tst 10 20 30 40 tst d.
: tst1 /[2"13'25* ; SEE tst1 3 12 tst1 d.[/code] LOG [code][4"1A'2F"32'41 \ (1c + 10) (2c - 15) (3c + 2) (4c - 1) b +c#-c#+c#-c#
CODE tst 60B133 8345080A ADD 8 [EBP] , # 10 60B137 836D040F SUB 4 [EBP] , # 15 60B13B 83450002 ADD 0 [EBP] , # 2 60B13F 8D40FF LEA EAX , FF [EAX] 60B142 C3 RET NEAR END-CODE ( 16 bytes, 5 instructions )
20 5 32 39
[2"13'25* b +c#-c#o
CODE tst1 60B153 83450003 ADD 0 [EBP] , # 3 60B157 8D40FB LEA EAX , FB [EAX] 60B15A F76D00 IMUL 0 [EBP] 60B15D 8D6D04 LEA EBP , 4 [EBP] 60B160 C3 RET NEAR END-CODE ( 14 bytes, 5 instructions )
42 [/code] PS. Синтаксис на данном этапе может меняться. В конечном итоге можно написать транспилятор для более удобного представления таких выражений, например аналогичных SPF-му виду для локальных переменных, только с возможностью многократного применения конструкций типа { a b c | d e f ... } и использования имен обычных слов форта. Сама текущая нотация будет первичным(промежуточным) языком.
|
|
|
 |
Добавлено: Чт апр 08, 2021 23:54 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Еще один способ работы с параметрами на стеке |
 |
|
Более сложный случай применения принятой модели вычислений: определим форму записи чисел с плав. точкой как 3,14159265, и напишем преобразователь из нее в форму, принятую в SPF. Код: \ 12 3456 1-a 2-u 3-sq 4-sz 5-pt 6-an : NOTFOUND /[20ddd12+1$Ib(0(:H?'3tIb(-=?I1-:5'4tL /321b(,-?`it`i=4y=&Z?12`N"1X;t /2iih:6162V(e62+w(.65+w62iv"1X ; Проверяем как это работает Код: \ длина окружности : Lkr. ( R -- Lkr) 2,0 /`*`P`*`. ; SEE Lkr. 10,0 Lkr. \ площадь круга : Skr. ( R -- Skr) /`d`*`P`*`. ; SEE Skr. 10,0 Skr. LOG Код: CODE Lkr. 60C1AB E8B87AF4FF CALL 553C68 ( _FLIT-CODE8 ) 60C1B0 A; 0 C, 0 C, 0 C, 0 C, 0 C, 0 C, 0 C, 40 C, 60C1B8 DEC9 FMULP ST(1) 60C1BA D9EB FLDPI 60C1BC DEC9 FMULP ST(1) 60C1BE E8DC67FAFF CALL 5B299F ( F. ) 60C1C3 C3 RET NEAR END-CODE ( 25 bytes, 6 instructions ) 62,831853
CODE Skr. 60C1D7 D9C0 FLD ST(0) 60C1D9 DEC9 FMULP ST(1) 60C1DB D9EB FLDPI 60C1DD DEC9 FMULP ST(1) 60C1DF E8BB67FAFF CALL 5B299F ( F. ) 60C1E4 C3 RET NEAR END-CODE ( 14 bytes, 6 instructions ) 314,15927 Ok
Более сложный случай применения принятой модели вычислений: определим форму записи чисел с плав. точкой как 3,14159265, и напишем преобразователь из нее в форму, принятую в SPF.
[code]\ 12 3456 1-a 2-u 3-sq 4-sz 5-pt 6-an : NOTFOUND /[20ddd12+1$Ib(0(:H?'3tIb(-=?I1-:5'4tL /321b(,-?`it`i=4y=&Z?12`N"1X;t /2iih:6162V(e62+w(.65+w62iv"1X ;[/code] Проверяем как это работает [code]\ длина окружности : Lkr. ( R -- Lkr) 2,0 /`*`P`*`. ; SEE Lkr. 10,0 Lkr. \ площадь круга : Skr. ( R -- Skr) /`d`*`P`*`. ; SEE Skr. 10,0 Skr.[/code] LOG [code]CODE Lkr. 60C1AB E8B87AF4FF CALL 553C68 ( _FLIT-CODE8 ) 60C1B0 A; 0 C, 0 C, 0 C, 0 C, 0 C, 0 C, 0 C, 40 C, 60C1B8 DEC9 FMULP ST(1) 60C1BA D9EB FLDPI 60C1BC DEC9 FMULP ST(1) 60C1BE E8DC67FAFF CALL 5B299F ( F. ) 60C1C3 C3 RET NEAR END-CODE ( 25 bytes, 6 instructions ) 62,831853
CODE Skr. 60C1D7 D9C0 FLD ST(0) 60C1D9 DEC9 FMULP ST(1) 60C1DB D9EB FLDPI 60C1DD DEC9 FMULP ST(1) 60C1DF E8BB67FAFF CALL 5B299F ( F. ) 60C1E4 C3 RET NEAR END-CODE ( 14 bytes, 6 instructions ) 314,15927 Ok[/code]
|
|
|
 |
Добавлено: Ср мар 31, 2021 23:39 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Еще один способ работы с параметрами на стеке |
 |
|
Увлекаться сокращением текста сильно не стоит, иначе будут получаться нечитаемые тексты. Вот пример слова определяющего мин. мах. и сумму байтов в строке. Код: : MaxMinSumBytes /[2{1b12GIb}M{Lcys}x1mx2x1+L"1. ; S" 325435463ehgfdchgGFFGKJH" MaxMinSumBytes LOG Код: h 2 1837 Ok
Увлекаться сокращением текста сильно не стоит, иначе будут получаться нечитаемые тексты. Вот пример слова определяющего мин. мах. и сумму байтов в строке. [code]: MaxMinSumBytes /[2{1b12GIb}M{Lcys}x1mx2x1+L"1. ; S" 325435463ehgfdchgGFFGKJH" MaxMinSumBytes[/code] LOG [code]h 2 1837 Ok[/code]
|
|
|
 |
Добавлено: Вт мар 30, 2021 00:50 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Еще один способ работы с параметрами на стеке |
 |
|
О реализация повторного использования кода на примере. Код: : example \ a1 (1) u1 (2) a2 (3) u2 (4) -- \ 1 2 /[4{24+dh}162V362+4V{65T}x1364V164+2V\x2"1X ; Выделяем кусок текста скобками { } а затем пишем х1 если повторяем первый выделенный таким образом кусок Сам выделенный кусок будет исполнятся, а x1 в коде будет компиляцией выделенного текста в другом месте. Следующий выделенный кусок обозначается как х2 и тд. Получается распределенный по коду словарик с именами х1.. хn. Разница только в том, что код в каждой позиции повторения может быть для одного выделения разным, так как в общем случае код позиционно зависимый. Семантика одинакова и соответствует исходному тексту.
О реализация повторного использования кода на примере. [code]: example \ a1 (1) u1 (2) a2 (3) u2 (4) -- \ 1 2 /[4{24+dh}162V362+4V{65T}x1364V164+2V\x2"1X ;[/code] Выделяем кусок текста скобками { } а затем пишем х1 если повторяем первый выделенный таким образом кусок Сам выделенный кусок будет исполнятся, а x1 в коде будет компиляцией выделенного текста в другом месте. Следующий выделенный кусок обозначается как х2 и тд. Получается распределенный по коду словарик с именами х1.. хn. Разница только в том, что код в каждой позиции повторения может быть для одного выделения разным, так как в общем случае код позиционно зависимый. Семантика одинакова и соответствует исходному тексту.
|
|
|
 |
Добавлено: Пн мар 29, 2021 19:46 |
|
|
 |
|