Более того, эту шизовую идею можно усовершенствовать.
Программа выше порождает вот такой подпрограммный шитый код :
Код:
14A3:00DE B83000 MOV AX,0030
14A3:00E1 50 PUSH AX
14A3:00E2 FF1E4800 CALL FAR [0048] ; call_косвенный NOOP ... ret
14A3:00E6 B80500 MOV AX,0005
14A3:00E9 50 PUSH AX
14A3:00EA FF1E4800 CALL FAR [0048] ; call_косвенный NOOP ... ret
14A3:00EE FF1E5400 CALL FAR [0054] ; call_косвенный _PLUS ... ret 4
14A3:00F2 50 PUSH AX
14A3:00F3 FF1E4800 CALL FAR [0048] ; call_косвенный NOOP ... ret
14A3:00F7 B83800 MOV AX,0038
14A3:00FA 50 PUSH AX
14A3:00FB FF1E4800 CALL FAR [0048] ; call_косвенный NOOP ... ret
14A3:00FF FF1E4C00 CALL FAR [004C] ; call_косвенный _DROP ... ret 2
14A3:0103 FF1E5000 CALL FAR [0050] ; call_косвенный _EMIT ... ret 2
14A3:0107 0E PUSH CS
14A3:0108 E8F5FE CALL 0000 ; call_прямой NOOP ... ret
В нем единственная явная кривизна - постоянные возовы подпрограммы NOOP,
которая вообще ничего не делает. Неряшливый в итоге получился код.
Но если заметить, что вызовы подпрограммы NOOP в любом случае занимают
четыре байта, то возникает идея - пусть подпрограмма NOOP сама свои
вызовы и заметает. Если в каком-либо месте кода она вызовется только
однократно, то это заметно на быстродействие кода не повлияет. А если этот
код выполняется неоднократно, то при первом вызове NOOP собственный вызов
затрет nop-ами и дальше код будет исполняться в соптимизированном виде.
Сделаем подпрограмму NOOP такой :
Код:
Procedure NOOP ;
Var I : Integer;
Begin
LongInt(Pointer(LongInt(Pointer(LongInt(@I) + 4)^) - 4)^) := $90909090
End;
Что породит в ней вот такой компактный код заметания собственных вызовов :
Код:
14A3:000E 8B4602 MOV AX,[BP+02]
14A3:0011 8B5604 MOV DX,[BP+04]
14A3:0014 2D0400 SUB AX,0004
14A3:0017 83DA00 SBB DX,+00
14A3:001A 89C7 MOV DI,AX
14A3:001C 8EC2 MOV ES,DX
14A3:001E 26 ES:
14A3:001F C7059090 MOV WORD PTR [DI],9090
14A3:0023 26 ES:
14A3:0024 C745029090 MOV WORD PTR [DI+02],9090
Здесь чтение [BP+02] и [BP+04] это ничто иное, как чтение адреса возврата.
В результате в процессе исполнения код программы сам превратится в :
Код:
14A3:00FF B83000 MOV AX,0030
14A3:0102 50 PUSH AX
14A3:0103 90 NOP
14A3:0104 90 NOP
14A3:0105 90 NOP
14A3:0106 90 NOP
14A3:0107 B80500 MOV AX,0005
14A3:010A 50 PUSH AX
14A3:010B 90 NOP
14A3:010C 90 NOP
14A3:010D 90 NOP
14A3:010E 90 NOP
14A3:010F FF1E5400 CALL FAR [0054] <- вызов _PLUS
14A3:0113 50 PUSH AX
14A3:0114 90 NOP
14A3:0115 90 NOP
14A3:0116 90 NOP
14A3:0117 90 NOP
14A3:0118 B83800 MOV AX,0038
14A3:011B 50 PUSH AX
14A3:011C 90 NOP
14A3:011D 90 NOP
14A3:011E 90 NOP
14A3:011F 90 NOP
14A3:0120 FF1E4C00 CALL FAR [004C] <- вызов _DROP
14A3:0124 FF1E5000 CALL FAR [0050] <- вызов _EMIT
14A3:0128 90 NOP
14A3:0129 90 NOP
14A3:012A 90 NOP
14A3:012B 90 NOP
Такая вот шизовая идея самооптимизирующегося подпрограммного шитого кода стек-машины средствами Паскаля.