Изначально программа была написана на Си++, потом переписана на Паскале (выяснилось, что работает быстрее) с использованием фрагментов на ассемблере, служащих для выявления сходимости ряда и вывода на экран в режиме SVGA (1024х768, 256 цветовых оттенков). А так как к ассемблеру отношусь крайне неравнодушно, то, разумеется, написал эту программу и на нем. В ней нет, конечно, функций постепенного увеличения изображения и увеличения/уменьшения количества просчетов при выявлении сходимости (все это делалось в программах на Си++ и Паскале с использованием "горячих клавиш"). Программируя на ассемблере, я преследовал особую цель: уменьшить размер самой программы. В первом варианте получилось 430 байт, во втором - 370. Показал друзьям - удивились, а один сострил: "Вот сделаешь программу размером в 100 байт, тогда я тебя зауважаю".
Сейчас я хочу представить на ваш суд программу размером 97 байт под девизом "Самая маленькая программа рисования фрактала Мандельбротта" или "Можно ли сделать меньше?" (см. листинг).
Пояснения к программе:
1. Крайняя левая координата по оси х=-2, по у=-1, крайняя правая по х=1, по у=1. (Для упрощения загрузки начальных координат рисовать начинаем с правого нижнего угла. Соответственно х и у начальные равны 1.) Так как выбран режим 320x200, то приращение по х и по у будут примерно одинаковы и равны 0,01.
2. Исследования ряда дали следующий результат: для выявления его сходимости достаточно сходимости его мнимой части, а не модуля комплексного числа.
3. Методом "научного тыка" получено, что достаточной константой для сравнения при выявлении сходимости является число 3 (или число p).
4. Разумеется, без команд ожидания нажатия клавиши после прорисовки и последующего возврата в 3-й текстовый режим размер программы будет 90 байт.
5. Для получения обещанного размера программы необходимо использовать компилятор TASM под DOS, так как, например, в режиме эмуляции DOS в Windows 95 или в DOS 7.0 перед каждой командой сопроцессора вставляется команда Wait, что не является обязательным. Исполняемый модуль должен иметь тип СОМ.
6. Для выполнения, конечно, необходимо наличие сопроцессора.
7. Перед командой Int 21h не стоит делать пересылку mov ah, ..., так как в конце прорисовки там оказывается значение 8, т. е. ввод символа с ожиданием. Команды db 0dbh,0e3h вместо finit и db 0dfh,0e0h вместо fstsw ax написаны из-за того, что перед ними постоянно любым компилятором ставится команда Wait.
Ну вот, пожалуй, и все пояснения. В окончательном варианте программа получилась, как это часто случается, очень простой.
Виталий Ланской - инженер-программист, работает на Чернобыльской АЭС, адрес в редакции.
Листинг
;Copyright # 1997 Lanskoi Vitali .387 _TEXT SEGMENT BYTE PUBLIC 'CODE' ORG 100h assume cs:_TEXT,ds:_TEXT START: mov al,13h ;Set VideoMode 13h= int 10h ;320x*200y*256colors mov bh,0a0h ;VideoMemSeg=A000 mov es,bx db 0dbh,0e3h ;finit fld1 ;High Y=1 fld1 ;Right X=1 fld2t ;Number for Comparing fldpi fidiv word ptr tudy+1 ;DelX=DelY=0.0098 mov bh,0fah ;BX=320*200 tudy: mov dx,320 ;Number Pixel's in paint: ; the string ; ***********Begin calculate Summa************** fld st(2) ;Re=X fld st(4) ;Im=Y mov cl,100 ;Number of Counts=100 cikl: fld st(1) ;Load Re fmul st,st ;st=Re*Re fld st(1) ;Load Im fmul st,st ;st=Im*Im fsubp st(1),st ;st=Re*Re-Im*Im fadd st,st(5) ;New Re=Re*Re-Im*Im+X fld st(2) ;Load Re fmul st,st(2) ;st=Re*Im fadd st,st ;st=2*Re*Im fadd st,st(7) ;New Im=2*Re*Im+Y fst st(2) ;Store New Im to Old Im fabs ; st(0)=FABS(Im) fcomp st(5) ; ? st(0)<3.3219 db 0dfh,0e0h ;fstsw ax fstp st(2) ;Store New Re to Old Re sahf jnc End_calc ;If st>3.3219 goto EndCalc loop cikl ;Continue calculate Summa ;************* End of calculation ******************** End_calc: fcompp st(1) ;clear st and increase stp(Twice) mov es:[bx],cl ; Write Pixel dec bx jz vse snova: fsub st(2),st ;X=X-DelX dec dx jnz paint ;Not end of string newstring: fld1 fstp st(3) ;Store 1 to X fsub st(3),st ;Y=Y-DelY jmp short tudy ;Continue paint vse: int 21h ;Wait KeyPress(ah=8) mov ax,3 int 10h ; Set TextMode 3 ret ; All !!! _TEXT ENDS END START