flat assembler
Message board for the users of flat assembler.
Index
> Main > Help with converting Delphi code. [beleberda detected] |
Author |
|
AsmGuru62 25 Apr 2014, 18:52
I think you first take FYL2X and then divide by MIN, but your formula says 1st divide by min and THEN take FYL2X.
|
|||
25 Apr 2014, 18:52 |
|
SeryZone 25 Apr 2014, 19:06
AsmGuru62 wrote: I think you first take FYL2X and then divide by MIN, but your formula says 1st divide by min and THEN take FYL2X. Okay, I correct: Code: format MS COFF include "Macro/Proc32.Inc" section ".code" executable public ModifyIndex C1 dd 1.0 C4096 dd 4096.0 proc ModifyIndex, min, dat1, dat2, step, Index ;Index := round( 4096 * sqrt(log2( (dat1+1-dat2)/min )/step)); finit fld [C4096];st5 fld [min] ;st4 fld [dat1] ;st3 fld [dat2] ;st2 fld [step] ;st1 fld1 ;st0 fadd st0, st3 fsub st0, st2 fdiv st0, st4 fyl2x fsqrt fdiv st0, st1 fmul st0, st5 frndint fstp [Index] ret endp and result stay as [2] |
|||
25 Apr 2014, 19:06 |
|
SeryZone 25 Apr 2014, 20:54
Where I got mistake??? please, tell!
|
|||
25 Apr 2014, 20:54 |
|
AsmGuru62 25 Apr 2014, 21:16
You have to check if parameters are passed/returned properly.
dat1, min are integer values, so they cannot be loaded with FLD, but with FILD. I suggest putting a breakpoint at the beginning (int3 opcode) and checking what debugger says and track how parameters are used. P.S. Delphi has a nice optimizer, so you may not get better code making the routine in FASM and then linking it with your program. Maybe some improvement needed in Delphi code itself? Like, here: round(4096* ...); better would be: 4096*round(...) Also, MUL by 4096 most likely optimized by Delphi as a shift, and in the FASM code you use FMUL, which is way slower. Another improvement: how many times that function called? probably millions of times... try to pass parameters inside of a structure, then the call will push a single parameter instead of 5 on each iteration. |
|||
25 Apr 2014, 21:16 |
|
SeryZone 26 Apr 2014, 07:09
Code: begin index := 0; step := log2(max/min); for y := 0 to maxy-1 do for x := 0 to maxx-1 do begin if (IterDat[x*maxy+y] >= max) then begin buffer[index] := 0; // red buffer[index + 1] := 0; // green buffer[index + 2] := 0; // blue end else if (IterDat[x*maxy+y] > 0) then begin ColorIndex := round( 4096 * (log2((Iterdat[x*maxy+y]+1-SmD[x*maxy+y])/min)/step) ) mod 4096; begin buffer[index] := pal[ColorIndex].b; // red buffer[index + 1] := pal[ColorIndex].g; // green buffer[index + 2] := pal[ColorIndex].r; // blue end; end; inc(index, 4) end; end; Here all code. 4096*round() I can't make because all values in round() between 0 and 1. And one. if on SSE or AVX i can calculate 4 or 8 sqrt() functions, but logarithm - only on FPU... |
|||
26 Apr 2014, 07:09 |
|
AsmGuru62 26 Apr 2014, 12:33
Yes, I just realized that it is not the same thing (I mean 4096).
I still suggest to put a breakpoint and examine what happens in the function in debugger. What are the types of your arrays? Iterdat SmD pal[x].r - is it BYTE? And other vars: min, max - are those integers? Code: ; buffer[index] := pal[ColorIndex].b; // red ; buffer[index + 1] := pal[ColorIndex].g; // green ; buffer[index + 2] := pal[ColorIndex].r; // blue Why .r commented as "// blue"? Is the comment wrong or the code wrong? |
|||
26 Apr 2014, 12:33 |
|
SeryZone 26 Apr 2014, 13:08
AsmGuru62 wrote: Yes, I just realized that it is not the same thing (I mean 4096). No, in delphi bgr, not rgb (I don't know, why). min, max - integers,but in improved code it single precision. Yes, pal[x]=(r:byte, g:byte, b:byte) |
|||
26 Apr 2014, 13:08 |
|
SeryZone 26 Apr 2014, 13:24
I tried to rewrite simple linear visualization, other types (sqrt, log2) I didn't write.
Code: format MS COFF include "Macro/Proc32.Inc" section ".code" executable public Linear public SquareRoot public Logarithmic C4096 dd 4096.0 DC rd 1 buffer dd ? step rd 1 ColorIndex rd 1 pal rb 4096*3 ;--------------------------------------------------------------------------------------------------; proc Linear bmp, data, width, height, min, max, palette ;bmp:TBitMap; data:array[0..Width*Heigth-1]of single, width, height:integer; min, max:single; palette: array of (byte, byte, byte); mov [width],eax ;eax = width imul [height] ;eax*height shl eax, 2 ;eax*4 invoke HeapAlloc,[buffer],HEAP_ZERO_MEMORY,eax ;make buffer size as eax elements finit fild [mim] ;st1, after st5 fild [max] ;st0, after st4 fsub st0, st1 ;step = max-min fst [step] ;store to memory mov [palette],edx ;load palette mov edx, [pal] ;12288 bytes mov [height], edi ;Height mov eax, edi dec edi mov ecx, 0 fory: ;counter is edi mov [width], edx dec edx forx: ;counter is edx fild [step] ;st3 fild [C4096] ;st2 fild [data+ecx*eax+edi];st1 fldz ;st0 = 0 ;ColorIndex := round( 4096 * ((data[x*maxy+y]-min)/step) ); fmov st0, st1 ;st0 = data fsub st0, st5 ;st0 = data-min fdiv st0, st3 ;st0 = (data-min)/step fmul st0, st2 ;st0 = 4096*((data-min)/step) frndint fstp [ColorIndex] mov [buffer+ecx], [pal*3+ColorIndex+3] ;Third index is blue mov [buffer+ecx], [pal*3+ColorIndex+2] ;Second index is green mov [buffer+ecx], [pal*3+ColorIndex+1] ;First index is red add ecx, 4 dec edx cmp edx, 0 jl forx dec edi cmp edi, 0 jl fory ret endp ;--------------------------------------------------------------------------------------------------; proc SquareRoot ret endp ;--------------------------------------------------------------------------------------------------; proc Logarithmic ret endp Delphi original: Code: 2: //linear begin index := 0; step := max-min; for y := 0 to maxy-1 do for x := 0 to maxx-1 do begin if (IterDat[x*maxy+y] >= max) then begin buffer[index] := 0; // red buffer[index + 1] := 0; // green buffer[index + 2] := 0; // blue end else if (IterDat[x*maxy+y] > 0) then begin ColorIndex := round( 4096 * ((Iterdat[x*maxy+y]-min)/step) ); begin buffer[index] := pal[ColorIndex].b; // red buffer[index + 1] := pal[ColorIndex].g; // green buffer[index + 2] := pal[ColorIndex].r; // blue end; end; inc(index, 4) end; end; SetDIBitsToDevice(DC, 0, 0, Maxx, Maxy,0,0,0, maxy, @Buffer[0], MyBMInfo, DIB_RGB_COLORS) So, help me, I know, that I got mistakes! =( |
|||
26 Apr 2014, 13:24 |
|
AsmGuru62 26 Apr 2014, 14:39
Here is some code (the whole thing):
Code: ; --------------------------------------------------------------------------- ; FILE: MakeImage.Asm ; DATE: April 26, 2014 ; --------------------------------------------------------------------------- struct PalItem red db ? green db ? blue db ? ends ; --------------------------------------------------------------------------- struct IParams ; ; Fill these members (in Delphi code) BEFORE calling MakeImage_Entry ; max dd ? ; integer min dd ? ; integer maxx dd ? ; integer maxy dd ? ; integer IterDat dd ? ; pointer to array of integers SmD dd ? ; pointer to array of integers buffer dd ? ; pointer to array of bytes (or PalItem structures?) pal dd ? ; pointer to array of PalItem structures ; ; These are used inside MakeImage_Entry as locals ; _4096 dd ? index dd ? x dd ? y dd ? step dq ? ; double ends align 32 MakeImage_Entry: ; --------------------------------------------------------------------------- ; INPUT (stdcall): ; Pointer to IParams instance ; --------------------------------------------------------------------------- push ebp mov ebp, esp push ebx esi edi mov ebp, [ebp + 8] ; EBP --> IParams structure xor eax, eax mov [ebp + IParams.index], eax ; index := 0 mov [ebp + IParams.y], eax ; y := 0 mov [ebp + IParams._4096], 4096 mov edi, [ebp + IParams.buffer] finit ; ; step := log2 (max/min) ; fld1 fild [ebp + IParams.max] fidiv [ebp + IParams.min] fyl2x fstp [ebp + IParams.step] ; ; for y := 0 to maxy-1 ; .next_y: and [ebp + IParams.x], 0 ; x := 0 ; ; for x := 0 to maxx-1 ; align 16 .inner_loop: mov esi, [ebp + IParams.IterDat] mov ebx, [ebp + IParams.SmD] ; ; ECX = x*maxy+y ; mov ecx, [ebp + IParams.x] imul ecx, [ebp + IParams.maxy] add ecx, [ebp + IParams.y] ; ; EAX = IterDat[ecx] ; mov eax, [esi + ecx*4] xor edx, edx ; ; if (IterDat[x*maxy+y] >= max) then set RGB=0 ; cmp eax, [ebp + IParams.max] jge .set_rgb_black ; ; else if (IterDat[x*maxy+y] > 0) ; cmp eax, edx jng .increase_x ; ; ColorIndex := round(4096 * (log2((Iterdat[x*maxy+y]+1-SmD[x*maxy+y])/min)/step)) mod 4096; ; mov edx, [ebx + ecx*4] ; EDX = SmD[ecx] ; ; EAX = Iterdat[x*maxy+y] + 1 - SmD[x*maxy+y] ; add eax, 1 sub eax, edx ; ; log2 (EAX/min) ; fld1 push eax fild dword [esp] fidiv [ebp + IParams.min] fyl2x fdiv [ebp + IParams.step] ; /step fimul [ebp + IParams._4096] ; *4096 fistp dword [esp] ; round (...) pop eax ; ; EAX mod 4096 ; mov ecx, 4096 xor edx, edx div ecx ; ; EDX is a ColorIndex ; lea eax, [edx + edx*2] ; EAX = 3*ColorIndex (PalItem is 3 bytes) mov ebx, [ebp + IParams.pal] add ebx, eax ; EBX points to pal[ColorIndex] ; ; buffer[index] := pal[ColorIndex].b; ; buffer[index + 1] := pal[ColorIndex].g; ; buffer[index + 2] := pal[ColorIndex].r; ; mov ecx, [ebp + IParams.index] mov al, [ebx + PalItem.blue] mov [edi + ecx], al mov al, [ebx + PalItem.green] mov [edi + ecx + 1], al mov al, [ebx + PalItem.red] mov [edi + ecx + 2], al jmp .increase_x .set_rgb_black: ; ; buffer[index] := 0; ; buffer[index + 1] := 0; ; buffer[index + 2] := 0; ; mov ecx, [ebp + IParams.index] mov [edi + ecx], edx ; ; Here ^^^: since index moves by 4 byte steps - I just write 4 zero bytes into buffer ; .increase_x: add [ebp + IParams.index], 4 add [ebp + IParams.x], 1 mov ecx, [ebp + IParams.x] cmp ecx, [ebp + IParams.maxx] jb .inner_loop ; ; Increase y ; add [ebp + IParams.y], 1 mov ecx, [ebp + IParams.y] cmp ecx, [ebp + IParams.maxy] jb .next_y .exit: pop edi esi ebx ebp ret 4 |
|||
26 Apr 2014, 14:39 |
|
SeryZone 26 Apr 2014, 20:35
AsmGuru62 wrote: Here is some code (the whole thing): Some questions: 1) What is 'align'? When I compile, I get error 'Section is not aligned enough' 2) If it don't visualize, then how to return buffer??? |
|||
26 Apr 2014, 20:35 |
|
AsmGuru62 26 Apr 2014, 21:54
1) try align 16 instead of align 32 or just comment it out.
2) I do not understand the concept of visualizing and how it is connected to returning a buffer. |
|||
26 Apr 2014, 21:54 |
|
SeryZone 27 Apr 2014, 07:15
AsmGuru62 wrote: 1) try align 16 instead of align 32 or just comment it out. So, code make calculations, but for visualization we need SetDIBitsToDevice() that can make Delphi program. For using SetDibits() program should return buffer array. |
|||
27 Apr 2014, 07:15 |
|
AsmGuru62 27 Apr 2014, 11:05
If you pass the buffer address in a structure - it will be filled by FASM code.
I would imagine the Delphi code go something like this: Code: { declare the instance of IParams structure (must be exact match to FASM code) } ... { fill members of IParams with max, min, maxx, maxy, buffer, pal, etc.} ... { call MakeImage_Entry (use stdcall) and pass IParams to it } ... { call SetDIBitsToDevice ( ... buffer ... )} buffer must be prepared before calling MakeImage_Entry. When MakeImage_Entry fills it pith pixels - pass it to SetDIBitsToDevice (). |
|||
27 Apr 2014, 11:05 |
|
SeryZone 27 Apr 2014, 13:10
AsmGuru62 wrote: If you pass the buffer address in a structure - it will be filled by FASM code. Yes, you are right. As I said, SetDIBitsToDevice need buffer variable. This variable declared in FASM procedure. Need to make buffer as output parameter... |
|||
27 Apr 2014, 13:10 |
|
AsmGuru62 27 Apr 2014, 22:08
The buffer must be declared BEFORE the FASM procedure called.
I take buffer from inside IParams structure. |
|||
27 Apr 2014, 22:08 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.