Рассмотрим варианты реализации в коде конкатенации строк для SPF и VFX,
в которых как раз используется глазковая оптимизация.
Код:
\ SPF
: s+(spf) ( a1 u1 a2 u2 -- a u )
>R OVER R@ + ALLOCATE THROW
DUP >R -ROT >R DUP >R MOVE
R> R> R> ROT 2DUP + -ROT R@
-ROT >R >R MOVE R> R> R> +
;
: s+(spfl) { a1 u1 a2 u2 \ a -- a u }
u1 u2 + ALLOCATE THROW TO a
a1 a u1 MOVE a2 a u1 + u2 MOVE a u1 u2 +
;
SEE s+(spf)
SEE s+(spfl)
CODE s+(spf)
5DA2A3 50 PUSH EAX
5DA2A4 8B4504 MOV EAX , 4 [EBP]
5DA2A7 030424 ADD EAX , [ESP]
5DA2AA E8EDACF7FF CALL 554F9C ( ALLOCATE )
5DA2AF E800AEF7FF CALL 5550B4 ( THROW )
5DA2B4 50 PUSH EAX
5DA2B5 8B5504 MOV EDX , 4 [EBP]
5DA2B8 894504 MOV 4 [EBP] , EAX
5DA2BB 8B4500 MOV EAX , 0 [EBP]
5DA2BE 895500 MOV 0 [EBP] , EDX
5DA2C1 50 PUSH EAX
5DA2C2 8B4500 MOV EAX , 0 [EBP]
5DA2C5 50 PUSH EAX
5DA2C6 8D6D04 LEA EBP , 4 [EBP]
5DA2C9 E8B69AF7FF CALL 553D84 ( MOVE )
5DA2CE 8945FC MOV FC [EBP] , EAX
5DA2D1 58 POP EAX
5DA2D2 59 POP ECX
5DA2D3 8BD1 MOV EDX , ECX
5DA2D5 59 POP ECX
5DA2D6 894DF4 MOV F4 [EBP] , ECX
5DA2D9 8955F8 MOV F8 [EBP] , EDX
5DA2DC 8BD1 MOV EDX , ECX
5DA2DE 8945F0 MOV F0 [EBP] , EAX
5DA2E1 8D0402 LEA EAX , [EDX] [EAX]
5DA2E4 8B55F4 MOV EDX , F4 [EBP]
5DA2E7 8945F4 MOV F4 [EBP] , EAX
5DA2EA 8B45F0 MOV EAX , F0 [EBP]
5DA2ED 8955F0 MOV F0 [EBP] , EDX
5DA2F0 8B0C24 MOV ECX , [ESP]
5DA2F3 8B55F0 MOV EDX , F0 [EBP]
5DA2F6 894DF0 MOV F0 [EBP] , ECX
5DA2F9 8955EC MOV EC [EBP] , EDX
5DA2FC 50 PUSH EAX
5DA2FD 8B45EC MOV EAX , EC [EBP]
5DA300 50 PUSH EAX
5DA301 8B45F0 MOV EAX , F0 [EBP]
5DA304 8D6DF4 LEA EBP , F4 [EBP]
5DA307 E8789AF7FF CALL 553D84 ( MOVE )
5DA30C 8945FC MOV FC [EBP] , EAX
5DA30F 58 POP EAX
5DA310 8945F8 MOV F8 [EBP] , EAX
5DA313 58 POP EAX
5DA314 59 POP ECX
5DA315 8D0408 LEA EAX , [EAX] [ECX]
5DA318 8D6DF8 LEA EBP , F8 [EBP]
5DA31B C3 RET NEAR
END-CODE
( 121 bytes, 47 instructions )
CODE s+(spfl)
5DA333 8945FC MOV FC [EBP] , EAX
5DA336 B810000000 MOV EAX , # 10
5DA33B 8D6DFC LEA EBP , FC [EBP]
5DA33E E8A58DF7FF CALL 5530E8 ( DRMOVE )
5DA343 8945FC MOV FC [EBP] , EAX
5DA346 B801000000 MOV EAX , # 1
5DA34B 8D6DFC LEA EBP , FC [EBP]
5DA34E E8D18EF7FF CALL 553224 ( (RALLOT) )
5DA353 6814000000 PUSH , # 14
5DA358 686C325500 PUSH , # 55326C
5DA35D 8945FC MOV FC [EBP] , EAX
5DA360 8B442414 MOV EAX , 14 [ESP]
5DA364 0344240C ADD EAX , C [ESP]
5DA368 8D6DFC LEA EBP , FC [EBP]
5DA36B E82CACF7FF CALL 554F9C ( ALLOCATE )
5DA370 E83FADF7FF CALL 5550B4 ( THROW )
5DA375 89442408 MOV 8 [ESP] , EAX
5DA379 8B442418 MOV EAX , 18 [ESP]
5DA37D 8945FC MOV FC [EBP] , EAX
5DA380 8B442408 MOV EAX , 8 [ESP]
5DA384 8945F8 MOV F8 [EBP] , EAX
5DA387 8B442414 MOV EAX , 14 [ESP]
5DA38B 8D6DF8 LEA EBP , F8 [EBP]
5DA38E E8F199F7FF CALL 553D84 ( MOVE )
5DA393 8945FC MOV FC [EBP] , EAX
5DA396 8B442410 MOV EAX , 10 [ESP]
5DA39A 8945F8 MOV F8 [EBP] , EAX
5DA39D 8B442408 MOV EAX , 8 [ESP]
5DA3A1 03442414 ADD EAX , 14 [ESP]
5DA3A5 8945F4 MOV F4 [EBP] , EAX
5DA3A8 8B44240C MOV EAX , C [ESP]
5DA3AC 8D6DF4 LEA EBP , F4 [EBP]
5DA3AF E8D099F7FF CALL 553D84 ( MOVE )
5DA3B4 8945FC MOV FC [EBP] , EAX
5DA3B7 8B442408 MOV EAX , 8 [ESP]
5DA3BB 8945F8 MOV F8 [EBP] , EAX
5DA3BE 8B442414 MOV EAX , 14 [ESP]
5DA3C2 0344240C ADD EAX , C [ESP]
5DA3C6 8D6DF8 LEA EBP , F8 [EBP]
5DA3C9 C3 RET NEAR
END-CODE
( 151 bytes, 40 instructions )
\ VFX
: s+(vfx) ( a1 u1 a2 u2 -- a u )
>R OVER R@ + ALLOCATE THROW
DUP >R -ROT >R DUP >R MOVE
R> R> R> ROT 2DUP + -ROT R@
-ROT >R >R MOVE R> R> R> +
;
: s+(vfxl) {: a1 u1 a2 u2 | a -- a u :}
u1 u2 + ALLOCATE THROW TO a
a1 a u1 MOVE a2 a u1 + u2 MOVE a u1 u2 +
SEE s+(vfx)
SEE s+(vfxl)
s+(vfx)
( 004D45D0 53 ) PUSH EBX
( 004D45D1 8B1C24 ) MOV EBX, [ESP]
( 004D45D4 035D04 ) ADD EBX, [EBP+04]
( 004D45D7 FF1591604100 ) CALL [00416091] ALLOCATE
( 004D45DD E82AECF3FF ) CALL 0041320C THROW
( 004D45E2 53 ) PUSH EBX
( 004D45E3 FF7500 ) PUSH [EBP]
( 004D45E6 8B5504 ) MOV EDX, [EBP+04]
( 004D45E9 52 ) PUSH EDX
( 004D45EA 895D04 ) MOV [EBP+04], EBX
( 004D45ED 8BDA ) MOV EBX, EDX
( 004D45EF 8D6D04 ) LEA EBP, [EBP+04]
( 004D45F2 E88902F3FF ) CALL 00404880 MOVE
( 004D45F7 5A ) POP EDX
( 004D45F8 59 ) POP ECX
( 004D45F9 58 ) POP EAX
( 004D45FA 8D6DEC ) LEA EBP, [EBP+-14]
( 004D45FD 894500 ) MOV [EBP], EAX
( 004D4600 895504 ) MOV [EBP+04], EDX
( 004D4603 894508 ) MOV [EBP+08], EAX
( 004D4606 894D0C ) MOV [EBP+0C], ECX
( 004D4609 895D10 ) MOV [EBP+10], EBX
( 004D460C 8BDA ) MOV EBX, EDX
( 004D460E 035D00 ) ADD EBX, [EBP]
( 004D4611 8B1424 ) MOV EDX, [ESP]
( 004D4614 FF7504 ) PUSH [EBP+04]
( 004D4617 FF7508 ) PUSH [EBP+08]
( 004D461A 895D08 ) MOV [EBP+08], EBX
( 004D461D 8BDA ) MOV EBX, EDX
( 004D461F 8D6D08 ) LEA EBP, [EBP+08]
( 004D4622 E85902F3FF ) CALL 00404880 MOVE
( 004D4627 5A ) POP EDX
( 004D4628 59 ) POP ECX
( 004D4629 58 ) POP EAX
( 004D462A 03C1 ) ADD EAX, ECX
( 004D462C 8D6DF8 ) LEA EBP, [EBP+-08]
( 004D462F 895500 ) MOV [EBP], EDX
( 004D4632 895D04 ) MOV [EBP+04], EBX
( 004D4635 8BD8 ) MOV EBX, EAX
( 004D4637 C3 ) NEXT,
( 104 bytes, 40 instructions )
SEE s+(vfxl)
s+(vfxl)
( 004D46A0 8BD4 ) MOV EDX, ESP
( 004D46A2 FF7508 ) PUSH [EBP+08]
( 004D46A5 FF7504 ) PUSH [EBP+04]
( 004D46A8 FF7500 ) PUSH [EBP]
( 004D46AB 53 ) PUSH EBX
( 004D46AC 52 ) PUSH EDX
( 004D46AD 57 ) PUSH EDI
( 004D46AE 8BFC ) MOV EDI, ESP
( 004D46B0 81EC04000000 ) SUB ESP, 00000004
( 004D46B6 8B5D0C ) MOV EBX, [EBP+0C]
( 004D46B9 8D6D10 ) LEA EBP, [EBP+10]
( 004D46BC 8B5708 ) MOV EDX, [EDI+08]
( 004D46BF 035710 ) ADD EDX, [EDI+10]
( 004D46C2 8D6DFC ) LEA EBP, [EBP+-04]
( 004D46C5 895D00 ) MOV [EBP], EBX
( 004D46C8 8BDA ) MOV EBX, EDX
( 004D46CA FF1591604100 ) CALL [00416091] ALLOCATE
( 004D46D0 E837EBF3FF ) CALL 0041320C THROW
( 004D46D5 895FFC ) MOV [EDI+-04], EBX
( 004D46D8 8D6DF8 ) LEA EBP, [EBP+-08]
( 004D46DB 8B5F10 ) MOV EBX, [EDI+10]
( 004D46DE 8B57FC ) MOV EDX, [EDI+-04]
( 004D46E1 895500 ) MOV [EBP], EDX
( 004D46E4 8B5714 ) MOV EDX, [EDI+14]
( 004D46E7 895504 ) MOV [EBP+04], EDX
( 004D46EA E89101F3FF ) CALL 00404880 MOVE
( 004D46EF 8B5710 ) MOV EDX, [EDI+10]
( 004D46F2 0357FC ) ADD EDX, [EDI+-04]
( 004D46F5 8D6DF4 ) LEA EBP, [EBP+-0C]
( 004D46F8 895500 ) MOV [EBP], EDX
( 004D46FB 8B570C ) MOV EDX, [EDI+0C]
( 004D46FE 895504 ) MOV [EBP+04], EDX
( 004D4701 895D08 ) MOV [EBP+08], EBX
( 004D4704 8B5F08 ) MOV EBX, [EDI+08]
( 004D4707 E87401F3FF ) CALL 00404880 MOVE
( 004D470C 8B5708 ) MOV EDX, [EDI+08]
( 004D470F 035710 ) ADD EDX, [EDI+10]
( 004D4712 8D6DF8 ) LEA EBP, [EBP+-08]
( 004D4715 8B4FFC ) MOV ECX, [EDI+-04]
( 004D4718 894D00 ) MOV [EBP], ECX
( 004D471B 895D04 ) MOV [EBP+04], EBX
( 004D471E 8BDA ) MOV EBX, EDX
( 004D4720 8B6704 ) MOV ESP, [EDI+04]
( 004D4723 8B3F ) MOV EDI, 0 [EDI]
( 004D4725 C3 ) NEXT,
( 134 bytes, 45 instructions )
ok
Теперь напишем это по другому ( в SPF )
Код:
: s+(spfsa) \ a1 u1 a2 u2 -- a u
DUP $ 8 A+@P ALLOCATE THROW
5$54354152 $ 0x14 @P+A $ 0xC @P+A MOVE MOVE
;
SEE s+(spfsa)
CODE s+(spfsa)
5DA3E3 8945FC MOV FC [EBP] , EAX
5DA3E6 8D6DFC LEA EBP , FC [EBP]
5DA3E9 034508 ADD EAX , 8 [EBP]
5DA3EC E8ABABF7FF CALL 554F9C ( ALLOCATE )
5DA3F1 E8BEACF7FF CALL 5550B4 ( THROW )
5DA3F6 8B5D0C MOV EBX , C [EBP]
5DA3F9 8B7500 MOV ESI , 0 [EBP]
5DA3FC 89450C MOV C [EBP] , EAX
5DA3FF 894500 MOV 0 [EBP] , EAX
5DA402 8945F4 MOV F4 [EBP] , EAX
5DA405 8B4508 MOV EAX , 8 [EBP]
5DA408 897508 MOV 8 [EBP] , ESI
5DA40B 8975FC MOV FC [EBP] , ESI
5DA40E 895DF8 MOV F8 [EBP] , EBX
5DA411 8D6DF4 LEA EBP , F4 [EBP]
5DA414 014500 ADD 0 [EBP] , EAX
5DA417 014500 ADD 0 [EBP] , EAX
5DA41A E86599F7FF CALL 553D84 ( MOVE )
5DA41F E86099F7FF CALL 553D84 ( MOVE )
5DA424 C3 RET NEAR
END-CODE
( 66 bytes, 20 instructions )
ПС.
Результат значительно лучше.
Просматривается другой более эффективный подход к оптимизации:
в стек забрасывается сразу необходимое(пусть и большое) количество параметров,
затем идут операции между параметрами как правило не фортовские,
с сохранением результатов не на вершине стека, а внутри стека
(стек при этом по глубине не меняется), в конечном итоге в стеке
лежит набор параметров, необходимый для последовательной работы слов,
выполняющим основной объем работы( в данном случае это MOVE MOVE ).
Такой подход похоже будет попроще в реализации и эффективнее по результату, чем глазковая оптимизация.