Изначально программа была написана на Си++, потом переписана на Паскале (выяснилось, что работает быстрее) с использованием фрагментов на ассемблере, служащих для выявления сходимости ряда и вывода на экран в режиме 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