Page 1 of 1

assembly question

Posted: Sun Jul 01, 2012 8:01 am
by basil99
Hi!
Have this simple assembly code in my PB programm

Code: Select all

		EnableASM

		PUSHAD
		
		MOV esi, S
		MOV edi, D
		MOV ecx, DrawWidth
		
FDloop:

		MOV eax, [esi]
		ADD esi, 4
		MOV [edi], eax
		ADD edi, 4
		DEC ecx
		JNZ FDloop

		POPAD

		DisableASM
try to compile and get this error messge:

Purebasic assembler error: JNZ FDloop error : undefined symbol 'FDloop'.

Whats wrong here ? any ideas ? Plese point my stupid head )
Thanks

Re: assembly question

Posted: Sun Jul 01, 2012 9:37 am
by J. Baker
!FDloop:

Re: assembly question

Posted: Sun Jul 01, 2012 12:44 pm
by wilbert
JNZ l_fdloop

Is also a possibility
When you reference a label, you must put the prefix 'l_' before the name. This is because PureBasic add a 'l_' before a BASIC label to avoid conflit with internal labels. The label need to be referenced in lowercase when using the inlined ASM.

Re: assembly question

Posted: Mon Jul 02, 2012 9:14 am
by basil99
Thanks for replies.

l_FDloop don't work, but !FDloop does.
Anyway, I need further assistance.
This assembly code:

Code: Select all

EnableASM

      PUSHAD
      
      MOV esi, S
      MOV edi, D
      MOV ecx, DrawWidth
      
!FDloop:

      MOV eax, [esi]
      ADD esi, 4
      MOV [edi], eax
      ADD edi, 4
      DEC ecx
      JNZ FDloop

      POPAD

      DisableASM



planned to be the assembly version of this PB code, that works fine:

Code: Select all

		For x = 1 To DrawWidth

			B = PeekI( S )
			S = S + 4
			PokeI( D, B )
			D = D + 4

		next x
So, PB code works, Assembly code crashed. Whats wrong ? Thanks

Re: assembly question

Posted: Mon Jul 02, 2012 9:31 am
by Thorium
If your code is in a procedure you mess up the stack index of the local variables with pushad. Thats why it crashes.

Try this:

Code: Select all

!push esi
!push edi

!mov esi, [p.v_S+8]
!mov edi, [p.v_D+8]
!mov ecx, [p.v_DrawWidth+8]

!FDloop:
  !mov eax, [esi]
  !add esi, 4
  !mov [edi], eax
  !add edi, 4
  !dec ecx
!jnz FDLoop

!pop edi
!pop esi

Re: assembly question

Posted: Mon Jul 02, 2012 10:36 am
by basil99
Thorium wrote:If your code is in a procedure you mess up the stack index of the local variables with pushad. Thats why it crashes.

Try this:

Code: Select all

!push esi
!push edi

!mov esi, [p.v_S+8]
!mov edi, [p.v_D+8]
!mov ecx, [p.v_DrawWidth+8]

!FDloop:
  !mov eax, [esi]
  !add esi, 4
  !mov [edi], eax
  !add edi, 4
  !dec ecx
!jnz FDLoop

!pop edi
!pop esi
Thanks, Thorium, tried it and get this error message:

!mov esi, [p.v_S+8] - error: undefined symbol 'p.v_S+8'

as for code, don't catch what you mean with "procedure". Code skeleton looks like this:

Code: Select all

S1 = Calculate( S1 )
D1 = Calculate( D1 )
DrawWidth = Calculate( DrawWidth )
DrawHeight = Calculate( DrawHeight )
Sstep = Calculate( Sstep )
Dstep = Calculate( Dstep )

for y = 1 to DrawHeight

    S = S1
    D = D1

    for x = 1 to DrawWidth

                    Code, we're talking about

     next x

     S = S + Sstep
     D = D + Dstep

next y


sure, its a part of a procedure for a DLL i try to code )

Re: assembly question

Posted: Mon Jul 02, 2012 10:56 am
by wilbert

Code: Select all

EnableASM

      MOV eax, S
      MOV edx, D
      MOV ecx, DrawWidth

      PUSH ebx      

!FDloop:

      MOV ebx, [eax]
      ADD eax, 4
      MOV [edx], ebx
      ADD edx, 4
      DEC ecx
      JNZ FDloop

      POP ebx

      DisableASM

Re: assembly question

Posted: Mon Jul 02, 2012 11:09 am
by Thorium
basil99 wrote: Thanks, Thorium, tried it and get this error message:

!mov esi, [p.v_S+8] - error: undefined symbol 'p.v_S+8'

as for code, don't catch what you mean with "procedure". Code skeleton looks like this:
The undefined symbol is actualy without the +8 and means it's a global variable. for global variables use only v_ not p.v_, p.v_ is only for local variables.

With procedure i mean if the code is located inside a procedure and uses local variables. Because local variables are on the stack, the stack index for them shifts if you push something to the stack. So you must add the number of bytes to the variable pointer that was been pushed to the stack.

Re: assembly question

Posted: Mon Jul 02, 2012 11:37 am
by basil99
Stiil confused (
Seems, need to explain more clear what i'm doing.

1. Third party code prepares a raw RGBA image ( actually BGRA ). I know image adress, image Width and Height, and image Pitch = len of one pixels line. Pitch in general is not equal to Width*4. Also, a destination adress is known, where i need to put "processed" image.

2. So, I decide to create a DLL for this, that would make all this job. Fiest step is just to copy source data into destination. Processing is another step, not significant to talk about here

3. Dll code is:

Code: Select all



ProcedureDLL ImageProcessing(  Width, Height, SourceAdress, DestAdress, Pitch )

S1 = SourceAdress
D1 = DesrAdress
DrawWidth = Width
DrawHeight = Height
Sstep = Pitch
Dstep = Pitch

for y = 1 to DrawHeight

    S = S1
    D = D1

    for x = 1 to DrawWidth

                B = PeekI( S )
         S = S + 4
         PokeI( D, B )
         D = D + 4


     next x

     S = S + Sstep
     D = D + Dstep

next y



EndProcedure


and this works perfect. But asembly not (

Re: assembly question

Posted: Mon Jul 02, 2012 12:26 pm
by Thorium
Dont know how i should explain it differently.

But as i wrote, this works:

Code: Select all

ProcedureDLL ImageProcessing(  Width, Height, SourceAdress, DestAdress, Pitch )

S1 = SourceAdress
D1 = DesrAdress
DrawWidth = Width
DrawHeight = Height
Sstep = Pitch
Dstep = Pitch

For y = 1 To DrawHeight

    S = S1
    D = D1

    !push esi
    !push edi
    
    !mov esi, [p.v_S+8]
    !mov edi, [p.v_D+8]
    !mov ecx, [p.v_DrawWidth+8]
    
    !FDLoop:
      !mov eax, [esi]
      !add esi, 4
      !mov [edi], eax
      !add edi, 4
      !dec ecx
    !jnz FDLoop
    
    !pop edi
    !pop esi

     S = S + Sstep
     D = D + Dstep

Next y

EndProcedure

Re: assembly question

Posted: Mon Jul 02, 2012 12:44 pm
by basil99
Great ! It works.
and I need to learn syntax better.
Thanks a lot for this

Re: assembly question

Posted: Mon Jul 02, 2012 12:54 pm
by Pupil
If you're only moving data from one place to another, why not use the built in 'CopyMemory()' function instead?

If pitch is same for source and destination I think something like this would work OK:

Code: Select all

CopyMemory(SourceAdress, DestAdress, (width*4+pitch)*height)

Re: assembly question

Posted: Mon Jul 02, 2012 2:22 pm
by basil99
Pupil wrote:If you're only moving data from one place to another, why not use the built in 'CopyMemory()' function instead?

If pitch is same for source and destination I think something like this would work OK:

Code: Select all

CopyMemory(SourceAdress, DestAdress, (width*4+pitch)*height)
Good idea, mate. I have smth more complex to do:

1) I need to make some operations with source image, like filter, effects etc

2) destination area may be an another image, smaller or bigger or equal then source one. So, some clipping is required ( omitted here )

3) Quick timing brings me the following : asm vesion 2.5-3 times faster then native PB peek/poke )

Re: assembly question

Posted: Thu Jul 05, 2012 5:03 pm
by Psychophanta
PB does allow to define variables, but does not allow to define labels inside a EnableASM-DisableASM block.
This looks like a clear bug to me.

Re: assembly question

Posted: Sun Jul 08, 2012 12:55 pm
by ultralazor
Even better.. why not just use PB? Maybe for your users sake since you don't know how a stack frame works?