Думаю сделать какое то описание этого процесса
![Smile :)](./images/smilies/icon_smile.gif)
Код на ForthEC для Колибри
Spoiler:
\ Allocate 28 bytes for the msg struct (actually 4+28)
variable rng 19 rng !
variable rngh 1 rngh !
variable video-buffer video-buffer 4 + video-buffer ! 65000 allot
variable screen screen 4 + screen ! 256000 allot
variable msg 28 allot
variable bih 36 allot
variable palette here ( palette 4 + palette ! ) 1030 allot palette !
variable done
variable last-time
: redraw
notouch
call init
call main
ret
redraw:
call draw_window
wait_event:
mov eax, 11
int 40h
dec eax
jz redraw
dec eax
jz key
dec eax
jz close
ret
close:
; button pressed; we have only one button, close
mov eax, -1
int 40h
key:
; key pressed, read it and ignore
mov eax, 2
int 40h
ret
jmp wait_event
touch
;
: draw_window
notouch
draw_window:
mov eax, 12
mov ebx, 1
int 40h ; start redraw
xor eax, eax
mov ebx, 50*65536 + 330 ; 360
mov ecx, 150*65536 + 228 ; 228
mov edx, 33FFFFFFh
mov edi, offset string ;title
int 40h ; define&draw window
; mov eax, 4
; mov ebx, 60*65536 + 10
; mov ecx, 80000000h
; mov edx, offset string
; int 40h ; draw string
; mov ebx, 50000h
; mov eax,dword ptr [var_0000000]
; mov ecx,dword ptr [eax]
; mov eax, 47
; mov edx, 20*65536 + 10
; mov esi, 0h ; color
; int 40h ; draw number
mov eax,dword ptr [var_0000002]
mov ebx, dword ptr [eax]
; mov edx, 2*65536 + 25 ; 150 x,y
; mov ecx, 320*65536 + 228 ; 50 size
mov edx, 0*65536 + 0 ; 150 x,y
mov ecx, 320*65536 + 200 ; 50 size
mov esi, 8
mov eax,dword ptr [var_0000006]
mov edi,dword ptr [eax]
mov ebp,0
mov eax,65
int 40h
mov eax, 12
mov ebx, 2
int 40h ; end redraw
ret
touch
;
\ Random number generator (borrowed from Paul Dixon)
: random ( -- n )
rngh rng notouch
pop esi
pop edi
mov edx,[edi]
shr edx,1
mov eax,[esi]
mov ecx,eax
rcr ecx,1
rcl edx,1
mov [edi],edx
shl eax,12
xor ecx,eax
mov eax,ecx
shr eax,20
xor ecx,eax
mov [esi],ecx
and ecx,191
mov eax,ecx
touch a@ ;
\ This draws the actual fire
: flames
12160 video-buffer @ +
12798 video-buffer @ +
160 0 do
over over
82 0 do
dup dup dup dup
c@ swap 2 + c@ + swap 4 + c@ + swap 644 + c@ + 2 >>
dup 0 <> if 1- then
dup 8 << or
dup 3 pick w!
2 pick 320 + w! swap 640 + swap 640 + loop
over 640 - random 10 + swap c!
drop drop swap 2 + swap 2 + loop drop drop ;
: setup-palette
palette @ 1024 -1 fill
palette @
33 1 do
i 3 << 1- \ pal c
over 0 swap !
over 2 + over swap c!
over 128 + 0 swap c!
over 129 + over swap c!
over 256 + c!
4 + loop drop
;
: draw-fire
flames
;
: win-main \ { hInst -- }
320 done !
\ Keep looping until the window is closed
begin
draw-fire
done @ dup 1- done ! 0= until
;
: main
notouch
main:
touch
setup-palette
\ Allocate room for a 320x200 bitmap, plus a little more
video-buffer 4 + video-buffer !
video-buffer @ 64000 0 fill
notouch
main1:
touch
win-main \ 19 rng !
notouch
call redraw
jmp main1
touch
;
Полученный листинг MASM
Spoiler:
; Generated by ForthEC
.686p
.mmx
.model flat,stdcall
option casemap:none
include ani.inc
;##############################################################################
pushdw macro pval
db 68h
dd pval
endm
;##############################################################################
.data
db 'MENUET01'
dd 1
dd offset _start
dd offset bss_start
dd offset bss_end
dd offset stacktop
dd 0, 0
title db 'HelloWorld test',0
string db 'FFire Demo',0
szFormatInt db "%d ",0
szFormatChar db "%hc",0
szBuffer db 256 dup(0)
szCR db 13,0
szLF db 10,0
.data?
bss_start label byte
align 4
db 1000h dup (?)
stacktop = $
stackBase dd ?
dictptr dd ?
dictionary dd 100000 dup(?)
ipstackptr dd ?
ipstack dd 256 dup(?)
fpstackptr dd ?
fpstack dq 128 dup(?)
loopstackptr dd ?
loopstack dd 64 dup(?)
miscstackptr dd ?
miscstack dd 64 dup(?)
hOutput dd ?
hInput dd ?
caseVar dd ?
lpCharsWritten dd ?
scratch1 dd ?
scratch2 dd ?
returnaddress dd ?
var_0000005 dd ?
var_0000007 dd ?
var_0000008 dd ?
var_0000004 dd ?
var_0000006 dd ?
var_0000000 dd ?
var_0000001 dd ?
var_0000003 dd ?
var_0000002 dd ?
bss_end label byte
;##############################################################################
.code
_start:
mov fpstackptr,offset fpstack
mov ipstackptr,offset ipstack
add ipstackptr,1024
mov dictptr,offset dictionary
mov miscstackptr,offset miscstack
mov loopstackptr,offset loopstack
; redraw
@@lbl_726564726177:
sub ipstackptr,4
mov eax,ipstackptr
pop dword ptr [eax]
call init
call main
ret
redraw:
call draw_window
wait_event:
mov eax, 11
int 40h
dec eax
jz redraw
dec eax
jz key
dec eax
jz close
ret
close:
; button pressed; we have only one button, close
mov eax, -1
int 40h
key:
; key pressed, read it and ignore
mov eax, 2
int 40h
ret
jmp wait_event
@@lbl_726564726177_return:
mov eax,ipstackptr
add ipstackptr,4
jmp dword ptr [eax]
; draw_window
@@lbl_647261775F77696E646F77:
sub ipstackptr,4
mov eax,ipstackptr
pop dword ptr [eax]
draw_window:
mov eax, 12
mov ebx, 1
int 40h ; start redraw
xor eax, eax
mov ebx, 50*65536 + 330 ; 360
mov ecx, 150*65536 + 228 ; 228
mov edx, 33FFFFFFh
mov edi, offset string ;title
int 40h ; define&draw window
; mov eax, 4
; mov ebx, 60*65536 + 10
; mov ecx, 80000000h
; mov edx, offset string
; int 40h ; draw string
; mov ebx, 50000h
; mov eax,dword ptr [var_0000000]
; mov ecx,dword ptr [eax]
; mov eax, 47
; mov edx, 20*65536 + 10
; mov esi, 0h ; color
; int 40h ; draw number
mov eax,dword ptr [var_0000002]
mov ebx, dword ptr [eax]
; mov edx, 2*65536 + 25 ; 150 x,y
; mov ecx, 320*65536 + 228 ; 50 size
mov edx, 0*65536 + 0 ; 150 x,y
mov ecx, 320*65536 + 200 ; 50 size
mov esi, 8
mov eax,dword ptr [var_0000006]
mov edi,dword ptr [eax]
mov ebp,0
mov eax,65
int 40h
mov eax, 12
mov ebx, 2
int 40h ; end redraw
ret
@@lbl_647261775F77696E646F77_return:
mov eax,ipstackptr
add ipstackptr,4
jmp dword ptr [eax]
; random
@@lbl_72616E646F6D:
sub ipstackptr,4
mov eax,ipstackptr
pop dword ptr [eax]
push dword ptr [var_0000001]
mov esi,dword ptr [var_0000000]
pop edi
mov edx,[edi]
shr edx,1
mov eax,[esi]
mov ecx,eax
rcr ecx,1
rcl edx,1
mov [edi],edx
shl eax,12
xor ecx,eax
mov eax,ecx
shr eax,20
xor ecx,eax
mov [esi],ecx
and ecx,191
mov eax,ecx
push eax
@@lbl_72616E646F6D_return:
mov eax,ipstackptr
add ipstackptr,4
jmp dword ptr [eax]
; flames
@@lbl_666C616D6573:
sub ipstackptr,4
mov eax,ipstackptr
pop dword ptr [eax]
add miscstackptr,4
mov eax,miscstackptr
mov [eax-4],ebp
mov ebp,loopstackptr
pushdw 12160
mov eax,dword ptr [var_0000002]
mov ebx,[eax]
add [esp],ebx
pushdw 12798
mov eax,dword ptr [var_0000002]
mov ebx,[eax]
add [esp],ebx
mov dword ptr [esp-4],160
mov dword ptr [esp-8],0
sub esp,8
mov eax,ebp
pop ecx
pop edx
add ebp,8
mov [eax],edx
mov [eax+4],ecx
@@loop_0000:
push dword ptr [esp+4]
push dword ptr [esp+4]
pushdw 82
mov esi,0
add ebp,8
pop edi
@@loop_0001:
push dword ptr [esp]
push dword ptr [esp]
push dword ptr [esp]
mov eax,[esp]
movzx ebx,byte ptr [eax]
mov eax,ebx
pop ecx
push eax
lea eax,[ecx+2]
movzx ebx,byte ptr [eax]
add [esp],ebx
pop eax
pop ecx
push eax
lea eax,[ecx+4]
movzx ebx,byte ptr [eax]
add [esp],ebx
pop eax
pop ecx
push eax
lea eax,[ecx+644]
movzx ebx,byte ptr [eax]
add [esp],ebx
mov ecx,2
shr dword ptr [esp],cl
cmp dword ptr [esp],0
jz @@if_000000_false
dec dword ptr [esp]
@@if_000000_false:
@@if_000000_true:
mov eax,dword ptr [esp]
shl eax,8
or [esp],eax
mov eax,dword ptr [esp+8]
mov ecx,dword ptr [esp]
mov [eax],cx
mov ecx,dword ptr [esp+8]
add ecx,320
pop eax
mov [ecx],ax
pop eax
pop ecx
push eax
lea eax,[ecx+640]
pop ecx
push eax
push ecx
add dword ptr [esp],640
inc esi
cmp esi,edi
jne @@loop_0001
@@loop_0001_end:
sub ebp,8
push dword ptr [esp+4]
mov eax,640
sub [esp],eax
call @@lbl_72616E646F6D
add dword ptr [esp],10
pop ecx
pop eax
mov [eax],cl
lea esp,[esp+8]
pop eax
pop ecx
push eax
lea eax,[ecx+2]
pop ecx
push eax
push ecx
add dword ptr [esp],2
lea eax,[ebp-8]
inc dword ptr [eax+4]
mov ecx,[eax]
cmp [eax+4],ecx
jne @@loop_0000
@@loop_0000_end:
sub ebp,8
lea esp,[esp+8]
@@lbl_666C616D6573_return:
sub miscstackptr,4
mov loopstackptr,ebp
mov esi,miscstackptr
mov ebp,[esi]
mov eax,ipstackptr
add ipstackptr,4
jmp dword ptr [eax]
; setup-palette
@@lbl_73657475702D70616C65747465:
sub ipstackptr,4
mov eax,ipstackptr
pop dword ptr [eax]
add miscstackptr,4
mov eax,miscstackptr
mov [eax-4],ebp
mov ebp,loopstackptr
mov eax,dword ptr [var_0000006]
push dword ptr [eax]
pushdw 1024
mov eax,-1
pop ecx
pop edi
rep stosb
mov eax,dword ptr [var_0000006]
push dword ptr [eax]
pushdw 33
mov esi,1
add ebp,8
pop edi
@@loop_0002:
push esi
shl dword ptr [esp],3
dec dword ptr [esp]
push dword ptr [esp+4]
mov eax,0
pop ecx
xchg eax,ecx
mov [eax],ecx
push dword ptr [esp+4]
add dword ptr [esp],2
mov ecx,dword ptr [esp+4]
pop eax
mov [eax],cl
push dword ptr [esp+4]
add dword ptr [esp],128
mov eax,0
pop ecx
xchg eax,ecx
mov [eax],cl
push dword ptr [esp+4]
add dword ptr [esp],129
mov ecx,dword ptr [esp+4]
pop eax
mov [eax],cl
push dword ptr [esp+4]
add dword ptr [esp],256
mov eax,[esp]
mov ecx,[esp+4]
mov [eax],cl
add esp,8
add dword ptr [esp],4
inc esi
cmp esi,edi
jne @@loop_0002
@@loop_0002_end:
sub ebp,8
lea esp,[esp+4]
@@lbl_73657475702D70616C65747465_return:
sub miscstackptr,4
mov loopstackptr,ebp
mov esi,miscstackptr
mov ebp,[esi]
mov eax,ipstackptr
add ipstackptr,4
jmp dword ptr [eax]
; draw-fire
@@lbl_647261772D66697265:
sub ipstackptr,4
mov eax,ipstackptr
pop dword ptr [eax]
call @@lbl_666C616D6573
@@lbl_647261772D66697265_return:
mov eax,ipstackptr
add ipstackptr,4
jmp dword ptr [eax]
; win-main
@@lbl_77696E2D6D61696E:
sub ipstackptr,4
mov eax,ipstackptr
pop dword ptr [eax]
mov eax,dword ptr [var_0000007]
mov dword ptr [eax],320
@@loop_0003:
call @@lbl_647261772D66697265
mov eax,dword ptr [var_0000007]
push dword ptr [eax]
push dword ptr [esp]
dec dword ptr [esp]
mov eax,dword ptr [var_0000007]
pop ecx
mov [eax],ecx
pop eax
xor ecx,ecx
sub esp,4
cmp eax,0
pop eax
jnz @@loop_0003
@@loop_0003_end:
@@lbl_77696E2D6D61696E_return:
mov eax,ipstackptr
add ipstackptr,4
jmp dword ptr [eax]
; main
@@lbl_6D61696E:
sub ipstackptr,4
mov eax,ipstackptr
pop dword ptr [eax]
main:
call @@lbl_73657475702D70616C65747465
push dword ptr [var_0000002]
add dword ptr [esp],4
mov eax,dword ptr [var_0000002]
pop ecx
mov [eax],ecx
mov eax,dword ptr [var_0000002]
push dword ptr [eax]
pushdw 64000
mov eax,0
pop ecx
pop edi
rep stosb
main1:
call @@lbl_77696E2D6D61696E
call redraw
jmp main1
@@lbl_6D61696E_return:
mov eax,ipstackptr
add ipstackptr,4
jmp dword ptr [eax]
;##############################################################################
init:
mov fpstackptr,offset fpstack
mov ipstackptr,offset ipstack
add ipstackptr,1024
mov dictptr,offset dictionary
mov miscstackptr,offset miscstack
mov loopstackptr,offset loopstack
mov eax,dictptr
mov var_0000000,eax
add dictptr,4
mov eax,dword ptr [var_0000000]
mov dword ptr [eax],19
mov eax,dictptr
mov var_0000001,eax
add dictptr,4
mov eax,dword ptr [var_0000001]
mov dword ptr [eax],1
mov eax,dictptr
mov var_0000002,eax
add dictptr,4
push dword ptr [var_0000002]
add dword ptr [esp],4
mov eax,dword ptr [var_0000002]
pop ecx
mov [eax],ecx
mov eax,65000
add dictptr,eax
mov eax,dictptr
mov var_0000003,eax
add dictptr,4
push dword ptr [var_0000003]
add dword ptr [esp],4
mov eax,dword ptr [var_0000003]
pop ecx
mov [eax],ecx
mov eax,256000
add dictptr,eax
mov eax,dictptr
mov var_0000004,eax
add dictptr,4
mov eax,28
add dictptr,eax
mov eax,dictptr
mov var_0000005,eax
add dictptr,4
mov eax,36
add dictptr,eax
mov eax,dictptr
mov var_0000006,eax
add dictptr,4
push dword ptr [dictptr]
mov eax,1030
add dictptr,eax
mov eax,dword ptr [var_0000006]
pop ecx
mov [eax],ecx
mov eax,dictptr
mov var_0000007,eax
add dictptr,4
mov eax,dictptr
mov var_0000008,eax
add dictptr,4
ret
END _start
Полученный листинг "ассемблируется" (превращается в obj), линкуется, транслируется (через использование скрипта doexe с помощью FASM) по методике описанной в Wiki
P.S. Для понимания действий по формированию Flames для себя расписал действия с ячейками памяти по данному коду на листочке.
(возможно имеет смысл отобразить дополнительно) и можно его, наверное если есть смысл, записать его более прозрачно средствами ForthEC или представить в виде мнемо-рисунка. Алгоритм формирования палитры более простой по действиям
![Smile :)](./images/smilies/icon_smile.gif)
(их можно переписать и на ассемблере)
ForthEC тоже подвергся некоторым доработкам по способу запуска кода. Можно убрать ещё некоторую избыточность кода программы
и поработать над компилятором ForthEC c опробованием разных опций оптимизации.
Выполнение кода начинается с кода первого слова redraw (название в этом месте чисто номинальное и более подходит, что то сообразное Entry)
А далее вызывается Init где производится инициализация стеков и main цикл по рисованию и опросу событий (в листинге ассемблера)
notouch ... touch прямая вставка MASM кода без изменений для компилятора (переменные в ассемблере из Форт идентифицируются по номеру)
Цикл по отрисовке заданного количество Flames в win-main избыточен (остался по недосмотру при "экспериментах" с кодом) наверное можно убрать. Работа примера не "оптимизировалась" для эмулятора (чем код необходимо дополнить)
P.P.S. Тему можно как то переобозначить если дополнить другими "элементами" и их описанием этого решения (кому будет интересно)
Есть интерес к рассмотрению "потенциала" и подводных камней данного подхода и варианты доработки "напильником" (головой и руками)
Архив с примером и ForthEC вариантом для Kolibri OS (в файле readme указана последовательность запуска bat файлов)
В системе должны присутствовать MASM32 и Euphoria (чувствительность к конкретной версии не проверялась 3-й или 4-ой)
Проект оригинального ForthEC находится здесь
Последняя версия ForthEC от автора на github