News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

ASM for FUN - #2 SUB

Started by frktons, April 21, 2010, 01:15:30 PM

Previous topic - Next topic

frktons

Here I am again.

Trying to intermix ASM CODE with PB CODE, but with no results.

I'm trying to introduce simple ASM instructions inside a PB SUB:

----------------------------------------------------------------------------------------------------------------------------
   ! PUSH ECX
   ! MOV ECX,1000000000
   ! cyclon:
   ! DEC ECX
   ! JNZ cyclon
   ! POP ECX
---------------------------------------------------------------------------------------------------------------------------       


the idea is to see how long it takes in CPU cycles to have 1 billion DEC of ECX register.

When the program arrives at ASM CODE it stops running.

Where am I doing wrong?

Thanks for the help

Frank
Mind is like a parachute. You know what to do in order to use it :-)

dedndave

are you sure it stops ? - lol
if you look at how big that number is, you may have to wait 100 years for the loop to finish
to test the implementation, try a smaller value like 1000

frktons

Quote from: dedndave on April 21, 2010, 01:30:56 PM
are you sure it stops ? - lol
if you look at how big that number is, you may have to wait 100 years for the loop to finish
to test the implementation, try a smaller value like 1000

Hi Dave.

The number is 1 billion, and it takes 1 second in PB, so it should take less in ASM.
I tried with 1000 it stops with that number as well. ::)
Mind is like a parachute. You know what to do in order to use it :-)

dedndave

well - i can think of 2 reasons it might hang
1) the compiler doesn't want you to use the ECX register, even if you do push/pop
2) the flags are modified and hold some critical info

is this inline ? or a routine
you might try putting it in a routine and calling it
the compiler may have a different set of "rules" for called routines

you may have to debug or disassemble it to see what code is actually generated
maybe you can get PB to generate an assembler listing
if that all makes sense, you may have to single-step though it

my mistake on the 100 years - i was thinking 64-bit values
i used the LOOP instruction once, and it took 3 seconds to count 4294967296
DEC ECX/JNZ is a bit faster than LOOP

frktons

Quote from: dedndave on April 21, 2010, 01:45:12 PM
well - i can think of 2 reasons it might hang
1) the compiler doesn't want you to use the ECX register, even if you do push/pop
2) the flags are modified and hold some critical info

is this inline ? or a routine
you might try putting it in a routine and calling it
the compiler may have a different set of "rules" for called routines

I tried with EAX as well but the outcome is the same.
It is INLINE ASM, that's what I'm trying to do, intermix some PB CODE with ASM.
From your comments it looks like there are no syntax or logical error, apparently.

Only somebody who is used to intermix PB/ASM can see where the problem is.
Mind is like a parachute. You know what to do in order to use it :-)

dedndave

maybe it doesn't understand the label
but, i would think that would spit out a compiler error

yes - the syntax looks fine
it looks like it would work in asm

frktons

I also tried to move the ASM OPCODES in a separate SUB:

----------------------------------------------------------------------
SUB ASM_001
   
   #REGISTER NONE
   ! PUSH ECX
   ! MOV ECX,1000000000
   ! ciclo:
   ! DEC ECX
   ! JNZ ciclo
   ! POP ECX

END SUB
---------------------------------------------------------------------


but the error is still there.
I don't think PB is capable of producing an ASM listing of the compilation,
but I'm not sure.
Mind is like a parachute. You know what to do in order to use it :-)

dedndave

here it is in assembler...

frktons

Quote from: dedndave on April 21, 2010, 02:01:33 PM
here it is in assembler...

Well it takes less than 1 second, but my goal is to see it running inside a PB SUB,
so I've to wait the help of somebody accustomed with this kind of mixing, or being lucky
and find the answer by myself surfing through the documentation and the internet.

It's a pity that a good compiler like PB has not a single tutorial book, but only reference docs.
Thanks anyway Dave.  :8)
Mind is like a parachute. You know what to do in order to use it :-)

dedndave

i think i found it
try removing the "!" in front of the label "cyclon:"
in asm, we tend to put labels all the way in the left column, too
that isn't a requirement, but it makes the code a little easier to follow

frktons

Quote from: dedndave on April 21, 2010, 02:10:35 PM
i think i found it
try removing the "!" in front of the label "cyclon:"
in asm, we tend to put labels all the way in the left column, too

It worked  :U
The INLINE ASM in PB can use variables declared in PB CODE and call or jump into
PB code apparently.

The strange thing is that the PB version:

   REGISTER i AS LONG, n AS LONG
   FOR i = 1 TO 1000000000
       INCR n
   NEXT

and the ASM version:

SUB ASM_001

    #REGISTER NONE
    ! PUSH ECX
    ! MOV ECX,1000000000
    ciclo:
    ! DEC ECX
    ! JNZ ciclo
    ! POP ECX

END SUB     

use the same number of cycles.

By the way, now that I moved the first step into the INLINE ASM of PB
the next step should be to use the routine [we discussed in the previous topic]
inside the PB CODE and see what happens. ::)


Thanks Dave
Mind is like a parachute. You know what to do in order to use it :-)

dedndave

they take the same time because the compiler optimizes that code to (probably) the same thing
if it were a more complicated code structure, the compiler might not be so lucky
in some cases, the compiler knows a few tricks, too
it all depends on who wrote it
from time to time, we can learn tricks from compiled code and use them in assembler
microsoft, for example, has hired some pretty sharp guys to write the C compilers
sometimes they can make optimizations that are top-notch, because the guys writing the compiler are well educated - lol

frktons

#12
Quote from: dedndave on April 21, 2010, 02:37:22 PM
they take the same time because the compiler optimizes that code to (probably) the same thing
if it were a more complicated code structure, the compiler might not be so lucky
in some cases, the compiler knows a few tricks, too
it all depends on who wrote it
from time to time, we can learn tricks from compiled code and use them in assembler
microsoft, for example, has hired some pretty sharp guys to write the C compilers
sometimes they can make optimizations that are top-notch, because the guys writing the compiler are well educated - lol

I couldn't agree with you more.  :8)

Working on ASM for FUN - #3 SUB  :P

See you
Mind is like a parachute. You know what to do in order to use it :-)

hutch--

Frank,

This works OK and is built with PBCC. 328 ms on my quad.


' «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
'
DECLARE FUNCTION GetTickCount LIB "KERNEL32.DLL" ALIAS "GetTickCount" () AS DWORD
'
' «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

FUNCTION PBmain as LONG

    #REGISTER NONE

    LOCAL tc as DWORD

    tc = GetTickCount

    ! mov ecx, 1000000000

  lbl0:
    ! sub ecx, 1
    ! jnz lbl0

    tc = GetTickCount - tc

    StdOut str$(tc)+" MS"

    Do
      Sleep 1
    Loop while inkey$ = ""

    ! pop esi

End FUNCTION

' «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

frktons

Quote from: hutch-- on April 22, 2010, 01:30:54 AM
Frank,

This works OK and is built with PBCC. 328 ms on my quad.


' «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
'
DECLARE FUNCTION GetTickCount LIB "KERNEL32.DLL" ALIAS "GetTickCount" () AS DWORD
'
' «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

FUNCTION PBmain as LONG

    #REGISTER NONE

    LOCAL tc as DWORD

    tc = GetTickCount

    ! mov ecx, 1000000000

  lbl0:
    ! sub ecx, 1
    ! jnz lbl0

    tc = GetTickCount - tc

    StdOut str$(tc)+" MS"

    Do
      Sleep 1
    Loop while inkey$ = ""

    ! pop esi

End FUNCTION

' «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««


Hi Hutch, thanks for this alternative way of counting performances in milliseconds.
It also gives me the opportunity to see how kernel32.dll functions can be used.  :U
Mind is like a parachute. You know what to do in order to use it :-)