flat assembler
Message board for the users of flat assembler.

Index > Linux > Buddhabrot Renderer

Author
Thread Post new topic Reply to topic
randall



Joined: 03 Dec 2011
Posts: 155
Location: Poland
randall 26 Apr 2012, 14:43
I have written small program that renders so called Buddhabrot.


Description:
Filesize: 98.86 KB
Viewed: 9619 Time(s)

buddhabrot5.jpg


Description:
Filesize: 45.1 KB
Viewed: 9619 Time(s)

buddhabrot2.jpg


Description:
Download
Filename: buddhabrot.asm
Filesize: 13.05 KB
Downloaded: 751 Time(s)

Post 26 Apr 2012, 14:43
View user's profile Send private message Visit poster's website Reply with quote
JohnFound



Joined: 16 Jun 2003
Posts: 3499
Location: Bulgaria
JohnFound 26 Apr 2012, 15:40
It looks great. How bad it is 64bit and I can't test it...
Post 26 Apr 2012, 15:40
View user's profile Send private message Visit poster's website ICQ Number Reply with quote
f0dder



Joined: 19 Feb 2004
Posts: 3175
Location: Denmark
f0dder 26 Apr 2012, 21:21
Too bad it's unportable Linux code - looks great Smile
Post 26 Apr 2012, 21:21
View user's profile Send private message Visit poster's website Reply with quote
typedef



Joined: 25 Jul 2010
Posts: 2909
Location: 0x77760000
typedef 27 Apr 2012, 01:52
^^Anything on computers is portable (portable as in implementation). Very Happy
Post 27 Apr 2012, 01:52
View user's profile Send private message Reply with quote
randall



Joined: 03 Dec 2011
Posts: 155
Location: Poland
randall 27 Apr 2012, 07:09
f0dder wrote:
Too bad it's unportable Linux code - looks great Smile


I just want to generate images with my programs and Linux is so much better for programming in asm. So simple, pure... only syscalls (interrupts) and your own code. On Windows I have to link with external library just to be able to create a file.
But I think that it would be very easy to port this code to Windows. Only image saving code is OS specific.
Post 27 Apr 2012, 07:09
View user's profile Send private message Visit poster's website Reply with quote
FreeFull



Joined: 10 Dec 2011
Posts: 2
FreeFull 30 Apr 2012, 14:10
This is pretty cool. Have you thought about allowing the parameters to be entered as arguments instead of being compiled into the executable? (although assembling doesn't take long at all)
Post 30 Apr 2012, 14:10
View user's profile Send private message Reply with quote
CandyMan



Joined: 04 Sep 2009
Posts: 413
Location: film "CandyMan" directed through Bernard Rose OR Candy Shop
CandyMan 02 May 2012, 16:40
Code:
        format  Flat on "vitamin.exe"
        entry   Start32
        stack   8k
        use64
;
Code16          = 90h   ; 16-bit compatibility mode code selector
Code32          = 38h   ; 32-bit compatibility mode code selector
Data32          = 30h   ; 32-bit compatibility mode data selector
Code64          = 28h   ; 64-bit code selector
BufferSize      = 32k   ; transfer buffer
;
macro   int No
{
        int No+80h
}
;
struc   RMCS    ;real mode call structure
{
.rEDI           dd ?    ;+0
virtual at .rEDI
.rDI            dw ?
end virtual
.rESI           dd ?    ;+4
virtual at .rESI
.rSI            dw ?
end virtual
.rEBP           dd ?    ;+8
virtual at .rEBP
.rBP            dw ?
end virtual
.Reserve        dd ?    ;+12
.rEBX           dd ?    ;+16
virtual at .rEBX
.rBX            dw ?
end virtual
virtual at .rBX
.rBL            db ?
.rBH            db ?
end virtual
.rEDX           dd ?    ;+20
virtual at .rEDX
.rDX            dw ?
end virtual
virtual at .rDX
.rDL            db ?
.rDH            db ?
end virtual
.rECX           dd ?    ;+24
virtual at .rECX
.rCX            dw ?
end virtual
virtual at .rCX
.rCL            db ?
.rCH            db ?
end virtual
.rEAX           dd ?    ;+28
virtual at .rEAX
.rAX            dw ?
end virtual
virtual at .rAX
.rAL            db ?
.rAH            db ?
end virtual
.rFL            dw ?    ;+32
.rES            dw ?    ;+34
.rDS            dw ?    ;+36
.rFS            dw ?    ;+38
.rGS            dw ?    ;+40
.rCSIP          dd ?    ;+42
virtual at .rCSIP
.rIP            dw ?
.rCS            dw ?
end virtual
.rSSSP          dd ?    ;+46
virtual at .rSSSP
.rSP            dw ?
.rSS            dw ?
end virtual
}
;
virtual at 0
RMCS            RMCS
end virtual
;
;I: rcx,rdx
;O: rax
WriteToFile:
        push    r8 rcx rdx rsi rdi rbp
        xor     r8d,r8d
        jrcxz   .End
        mov     rbp,rcx
        mov     rsi,rdx
      .Loop:
        mov     ecx,BufferSize
        sub     rbp,rcx
        jnc     .Write
        add     rbp,rcx
        mov     ecx,ebp
        xor     ebp,ebp
      .Write:
        push    rcx
        mov     edi,[LinBuff]
        shr     rcx,3
        rep     movsq
        mov     cl,[rsp]
        and     cl,111b
        rep     movsb
        pop     rcx
        mov     ah,40h
        call    DosIntWithBufferZero
        add     r8,rax
        or      rbp,rbp
        jnz     .Loop
      .End:
        mov     rax,r8
        pop     rbp rdi rsi rdx rcx r8
        ret

DosIntWithBufferZero:
        xor     edx,edx
DosIntWithBuffer:
        push    rbx rcx rdi
        lea     edi,[Regs]
        mov     [rdi+RMCS.rAH],ah
        mov     eax,[SegBuff]
        mov     [rdi+RMCS.rDS],ax
        mov     [rdi+RMCS.rES],ax
        mov     [rdi+RMCS.rEBX],ebx
        mov     [rdi+RMCS.rECX],ecx
        mov     [rdi+RMCS.rEDX],edx
        call    DosInt
        movzx   eax,[rdi+RMCS.rAX]
        bt      dword [rdi+RMCS.rFL],0
        pop     rdi rcx rbx
        ret

DosInt: mov     bl,21h
        mov     ax,0300h
        xor     bh,bh
        xor     ecx,ecx
        mov     [rdi+RMCS.rSSSP],ecx
        mov     [rdi+RMCS.rFL],1
        int     31h
        ret
Start32:
        use32
        jmp     Code64:Start64
        use64
;-------------------------------------------------------------------------------
; NAME: XORWOW
; DESC: Pseudo random number generator.
; OUT:  eax     [0;2^32-1]
;-------------------------------------------------------------------------------
macro   XORWOW  {
        mov     edx,[g_xorwow_x]   ; edx = x
        shr     edx,2              ; edx = x >> 2
        xor     edx,[g_xorwow_x]   ; t = x ^ (x >> 2)
        mov     eax,[g_xorwow_y]   ; eax = y
        mov     [g_xorwow_x],eax   ; x = y
        mov     eax,[g_xorwow_z]   ; eax = z
        mov     [g_xorwow_y],eax   ; y = z
        mov     eax,[g_xorwow_w]   ; eax = w
        mov     [g_xorwow_z],eax   ; z = w
        mov     eax,[g_xorwow_v]   ; eax = v
        mov     [g_xorwow_w],eax   ; w = v
        mov     edi,eax            ; edi = v
        shl     edi,4              ; edi = v << 4
        xor     edi,eax            ; edi = (v ^ (v << 4))
        mov     eax,edx            ; eax = t
        shl     eax,1              ; eax = t << 1
        xor     eax,edx            ; eax = (t ^ (t << 1))
        xor     eax,edi            ; eax = (v ^ (v << 4)) ^ (t ^ (t << 1))
        mov     [g_xorwow_v],eax   ; v = eax
        add     [g_xorwow_d],362437; d += 362437
        mov     eax,[g_xorwow_d]   ; eax = d
        add     eax,[g_xorwow_v]   ; eax = d + v
}
;-------------------------------------------------------------------------------
; NAME: RANDOM
; DESC: Returns pseudo random number in the range [-0.5;0.5).
; OUT:  xmm0.x  [-0.5;0.5)
;-------------------------------------------------------------------------------
macro   RANDOM {
        XORWOW
        cvtsi2ss xmm0,eax
        mulss   xmm0,[g_rand_scale]
}
;-------------------------------------------------------------------------------
; NAME: GenerateSequence
; IN:   xmm0.x  re (c0.x)
; IN:   xmm1.x  im (c0.y)
; IN:   rdi     array size
; IN:   rsi     pointer to the allocated array
; OUT:  rax     generated sequence size
;-------------------------------------------------------------------------------
even 16
GenerateSequence:
        xor     eax,eax         ; eax is index loop
        xorps   xmm4,xmm4       ; xmm4 is c.x
        xorps   xmm5,xmm5       ; xmm5 is c.y
.Loop:
        ; cn.x = c.x * c.x - c.y * c.y + c0.x
        movaps  xmm2,xmm4
        movaps  xmm3,xmm5
        mulss   xmm2,xmm4
        mulss   xmm3,xmm5
        subss   xmm2,xmm3
        addss   xmm2,xmm0
        movaps  xmm6,xmm2       ; xmm6 is cn.x
        ; cn.y = 2.0 * c.x * c.y + c0.y
        movaps  xmm7,xmm4
        mulss   xmm7,xmm5
        addss   xmm7,xmm7
        addss   xmm7,xmm1       ; xmm7 is cn.y
        ; store cn
        movd    dword [rsi+rax*8+0],xmm6
        movd    dword [rsi+rax*8+4],xmm7
        ; if (cn.x * cn.x + cn.y * cn.y > 10.0) return eax;
        movaps  xmm2,xmm6
        movaps  xmm3,xmm7
        mulss   xmm2,xmm6
        mulss   xmm3,xmm7
        addss   xmm2,xmm3
        ucomiss xmm2,[g_max_dist]
        ja      .EndLoop
        movaps  xmm4,xmm6       ; c.x = cn.x
        movaps  xmm5,xmm7       ; c.y = cn.y
        ; continue loop
        inc     eax
        cmp     eax,edi
        jb      .Loop
        ; return 0
        xor     eax,eax
.EndLoop:
        ret
;-------------------------------------------------------------------------------
; NAME: AllocateMemory
; IN:   rdi     size in bytes
; OUT:  rax     memory address
;-------------------------------------------------------------------------------
even 16
AllocateMemory:
        mov     rax,[MemoryStart]
        add     [MemoryStart],rdi
        push    rax rdi
        mov     rcx,rdi
        shr     rcx,3
        mov     rdi,rax
        xor     eax,eax
        rep     stosq
        pop     rcx
        and     ecx,111b
        rep     stosb
        pop     rax
        ret
;-------------------------------------------------------------------------------
; NAME: Main
; DESC: Program main function.
;-------------------------------------------------------------------------------
align 16
Main:
ImgPtr  equ     rbp-08
SeqPtr  equ     rbp-16
Pixel   equ     rbp-24
        push    rbp
        mov     rbp,rsp
        sub     rsp,128
        ; alloc mem for the sequence
        mov     edi,SEQ_SIZE*8
        call    AllocateMemory
        mov     [SeqPtr],rax
        ; alloc mem for the image
        mov     edi,IMG_SIZE*IMG_SIZE*4
        call    AllocateMemory
        mov     [ImgPtr],rax
        ; begin loops
        xor     r13d,r13d       ; .LoopIterations counter
.LoopIterations:
        xor     r12d,r12d       ; .LoopOneMillion counter
.LoopOneMillion:
        RANDOM
        mulss   xmm0,[g_range]
        movaps  xmm1,xmm0
        RANDOM
        mulss   xmm0,[g_range]
        mov     edi,SEQ_SIZE
        mov     rsi,[SeqPtr]
        call    GenerateSequence; eax = n sequence size
        test    eax,eax
        jz      .LoopSequenceEnd
        xor     ecx,ecx         ; ecx = i = 0 loop counter
        mov     r9,[SeqPtr]     ; r9 = sequence base address
        mov     r8,[ImgPtr]     ; r8 = image base address
        movss   xmm2,[g_img_size]
        movaps  xmm3,xmm2
        mulss   xmm3,[g_0_5]    ; xmm3 = (g_img_size)/2
        movss   xmm4,[g_zoom]
        mulss   xmm4,xmm2       ; xmm4 = g_zoom * g_img_size
        movss   xmm5,[g_offsetx]; xmm5 = g_offsetx
        movss   xmm6,[g_offsety]; xmm6 = g_offsety
.LoopSequence:
        cmp     ecx,eax         ; i < n
        je      .LoopSequenceEnd
        movd    xmm0,[r9+rcx*8+0] ; load re
        movd    xmm1,[r9+rcx*8+4] ; load im
        addss   xmm0,xmm5       ; xmm0 = re+g_offsetx
        addss   xmm1,xmm6       ; xmm1 = im+g_offsety
        mulss   xmm0,xmm4       ; xmm0 = (re+g_offsetx)*g_img_size*g_zoom
        mulss   xmm1,xmm4       ; xmm1 = (im+g_offsety)*g_img_size*g_zoom
        addss   xmm0,xmm3       ; xmm0 = (re+g_offsetx)*g_img_size*g_zoom+g_img_size/2
        addss   xmm1,xmm3       ; xmm1 = (im+g_offsety)*g_img_size*g_zoom+g_img_size/2
        cvtss2si edi,xmm0       ; edi = x = int(xmm0.x)
        cvtss2si esi,xmm1       ; esi = y = int(xmm1.x)
        or      edi,edi
        jl      @F
        cmp     edi,IMG_SIZE
        jge     @F
        or      esi,esi
        jl      @F
        cmp     esi,IMG_SIZE
        jge     @F
        imul    esi,esi,IMG_SIZE
        add     esi,edi
        inc     dword [r8+rsi*4]
      @@:
        inc     ecx
        jmp     .LoopSequence
.LoopSequenceEnd:
        ; continue .LoopOneMillion
        inc     r12d
        cmp     r12d,1000000
        jb      .LoopOneMillion
        ; continue .LoopIterations
        inc     r13d
        cmp     r13d,ITERATIONS
        jb      .LoopIterations
        ; find max value
        mov     r8,[ImgPtr]     ; r8 = image base address
        xor     r12d,r12d       ; r12d = max_val = 0
        xor     eax,eax         ; eax = i = loop counter
.LoopMax:
        cmp     [r8+rax*4],r12d
        cmova   r12d,[r8+rax*4]
        inc     eax
        cmp     eax,IMG_SIZE*IMG_SIZE
        jb      .LoopMax
        ; find min value
        mov     r13d,r12d       ; r13d = min_val = max_val
        xor     eax,eax         ; eax = i = loop counter
.LoopMin:
        cmp     [r8+rax*4],r13d
        cmovb   r13d,[r8+rax*4]
        inc     eax
        cmp     eax,IMG_SIZE*IMG_SIZE
        jb      .LoopMin
        ; create TGA file
        mov     ah,3Ch
        lea     edx,[g_tga_name]
        xor     ecx,ecx
        int     21h
        xchg    ebx,eax
        ; write TGA header
        lea     edx,[g_tga_head]
        mov     ecx,18
        call    WriteToFile
        ; write image pixels
        mov     byte [Pixel+3],255
        mov     r14,[ImgPtr]    ; r14 = image base address
        xor     r15d,r15d       ; r15d = i = loop counter
        cvtsi2ss xmm0,r12d      ; load max_value
        cvtsi2ss xmm1,r13d      ; load min_value
        movaps  xmm2,xmm0
        subss   xmm2,xmm1       ; xmm2 = r = max_value - min_value
.LoopWrite:
        mov     eax,[r14+r15*4] ; eax = image_value
        sub     eax,r13d        ; eax = image_value - min_value
        cvtsi2ss xmm0,eax       ; xmm0 = float(image_value - min_value)
        addss   xmm0,xmm0       ; xmm0 = 2.0f * float(image_value - min_value)
        divss   xmm0,xmm2       ; xmm0 = 2.0f * float(image_value - min_value) / r
        minss   xmm0,[g_1_0]    ; clamp to 1.0
        maxss   xmm0,[g_0_0]    ; clamp to 0.0
        mulss   xmm0,[g_255_0]  ; convert to 0 - 255
        cvtss2si eax,xmm0
        mov     [Pixel+0],al    ; store B component
        mov     [Pixel+1],al    ; store G component
        mov     [Pixel+2],al    ; store R component
        ; write pixel data
        lea     edx,[Pixel]
        mov     ecx,4-1
        call    WriteToFile
        ; continue .LoopWrite
        inc     r15d
        cmp     r15d,IMG_SIZE*IMG_SIZE
        jb      .LoopWrite
        ; close file
        mov     ah,3Eh
        int     21h
        mov     rsp,rbp
        pop     rbp
        ret
        restore ImgPtr,SeqPtr,Pixel
;-------------------------------------------------------------------------------
; NAME: Start64
; DESC: Program entry point.
;-------------------------------------------------------------------------------
Start64:
        push    0
        syscall
        mov     [ExitAddr],r8
        mov     [BufferVar],rcx
        call    Main
        xor     al,al
        jmp     [ExitAddr]
;-------------------------------------------------------------------------------
even 1
g_tga_name      db 'picture.tga',0
g_tga_head      db 0,0,2,9 dup 0
                db (IMG_SIZE and 0x00FF),(IMG_SIZE and 0xFF00) shr 8
                db (IMG_SIZE and 0x00FF),(IMG_SIZE and 0xFF00) shr 8,32-8,0
even 4
g_xorwow_x      dd 123456789
g_xorwow_y      dd 362436069
g_xorwow_z      dd 521288629
g_xorwow_w      dd 88675123
g_xorwow_v      dd 5783321
g_xorwow_d      dd 6615241
g_rand_scale    dd 2.3283064e-10; 1.0 / 2^32

IMG_SIZE        = 800
SEQ_SIZE        = 50
ITERATIONS      = 100   ;1000

g_img_size      dd 800.0
g_offsetx       dd 0.5
g_offsety       dd 0.0
g_zoom          dd 0.4

g_max_dist      dd 10.0
g_range         dd 4.2
g_0_5           dd 0.5
g_0_0           dd 0.0
g_1_0           dd 1.0
g_255_0         dd 255.0
;-------------------------------------------------------------------------------
MemoryStart     dq MemStrt
ExitAddr        dq ?
;
BufferVar:
LinBuff         dd ?    ;transfer buffer *linear address
SegBuff         dd ?    ;transfer buffer segment address
;
Regs            RMCS
;-------------------------------------------------------------------------------
even 16
MemStrt         rb SEQ_SIZE*8+IMG_SIZE*IMG_SIZE*4
;-------------------------------------------------------------------------------
    

fasm you can download from:
http://board.flatassembler.net/topic.php?t=12811
Post 02 May 2012, 16:40
View user's profile Send private message Reply with quote
macgub



Joined: 11 Jan 2006
Posts: 346
Location: Poland
macgub 09 May 2012, 06:45
I ported randall code into KolibriOS. Now it 32bit.
http://macgub.co.pl/menuet/buddhabrot.zip
Post 09 May 2012, 06:45
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.