FB II Compiler

PG PRO

Debugging

Memory

System

Mathematics

Resources

Disk I/O

Windows

Controls

Menus

Mouse

Keyboard

Text

Fonts

Drawing

Sound

Clipboard

Printing

Communication

ASM

Made with FB

ASSEMBLER

Compare ASM with FB


<< I have this routine in FBII basic code, but is too slow for my. Everyone that made this in Asm code for my is free for a week or more at my home in Venice..... >>

While not in assembler, this should at least be a lot faster if you call it often:

LOCAL
  DIM punta%
LOCAL FN nuovacolonna(punta%) '(Gcolonna$,Gpt)
  SELECT PEEK (@Gcolonna$+punta%)
    CASE 49 'ASCII Code for a 1
      POKE (@Gcolonna$+punta%),88
    CASE 88 'ASCII Code for a capital X
      POKE (@Gcolonna$+punta%),50
    CASE 50 'ASCII Code for a 2
      LONG IF punta% < 13
        POKE (@Gcolonna$+punta%),49
        INC(punta%)
        FN nuovacolonna(punta%)
      END IF
  END SELECT
END FN

The only difference is that I replaced complex string operations with simpler number compares by using PEEK to look at the contents of the string in the same way that you had been using MID$. After that, it's a lot faster to just POKE in the actual ASCII code than to use MID$. You might also want to try removing the recursive function call, but without knowing exactly what you're doing I won't mess with that.

Joe K.


I think the first byte of pascal string is length, so to access directly, offset must be add 1.

ex. POKE (@Gcolonna$+punta%+1),88

LOCAL
  DIM punta,a$
LOCAL FN nuovacolonna(punta) '(Gcolonna$,Gpt)
  adr& = @Gcolonna$+punta+1
  SELECT PEEK(adr&)
    CASE _"1"
      POKE adr&,_"X"
    CASE _"X"
      POKE adr&,_"2"
    CASE _"2"
      LONG IF punta < 13
        POKE adr&,"1"
        INC(punta)
        FN nuovacolonna(punta)
      END IF
  END SELECT
END FN

Note that you must check the length of Gcolonna and punta must be small than it.

The following code is not tested, but just compiled. It be seemed OK.

COMPILE 0,_macsbuglabels
LOCAL FN nuovacolonna(punta%)
 REGISTER(a0) = @Gcolonna$
  ` ADD.L ^punta%,A0
  ` ADDQ.L #1,A0
  ` MOVE.B (A0),D0
  ` CMPI.B #49,D0
  ` BNE @1
  ` MOVE.B #88,(A0)
  ` BRA @EXIT
  `@1
  ` CMPI.B #88,D0
  ` BNE @2
  ` MOVE.B #50,(A0)
  ` BRA @EXIT
  `@2
  ` CMPI.B #50,D0
  ` BNE @EXIT
  ` MOVE.W ^punta%,D0
  ` CMPI.B #13,D0
  ` BCC @EXIT
  ` MOVE.B #49,(A0)
  ` ADDQ.L #1,D0
  ` MOVE.W D0,^punta%
  FN nuovacolonna(punta%)
  `@EXIT
END FN


Whoohoo, hey, I'll bite - a week in Venice? Does this include airfare? <g>

The following version of FN nuovacolonna runs 100,000 iterations in 31 ticks on my machine, as opposed to 181 ticks for the original.

LOCAL
  DIM punta,a$
  DIM gColPtr&, gAstrPtr&
LOCAL FN nuovacolonna(punta%) '(Gcolonna$,Gpt)
  gColPtr& = @Gcolonna$
  `nuovacolonna_top
  ` move.w ^punta%, D1
  ` ext.l D1
  ` addq.l #$1,D1
  ` move.l ^gColPtr&, A0
  ` adda.l D1,A0
  ` clr.w D0
  ` move.b (A0), D0
  ` cmpi.w #49, D0
  ` bne.s caseeightyeight
  `casefortynine
  ` move.b #88, (A0)
  ` bra.s end_select
  `caseeightyeight
  ` cmpi.w #88, D0
  ` bne.s casefifty
  ` move.b #50, (A0)
  ` bra.s end_select
  `casefifty
  ` cmpi.w #50, D0
  ` bne.s end_select
  ` cmpi.w #14, D1
  ` bgt.s end_select
  ` move.b #49, (A0)
  ` move.w D1, ^punta%
  ` bra nuovacolonna_top
  `end_select
END FN

Mars


This will be about 50 times as fast and you don't have to use any assembly.

LOCAL FN nuovacolonna(punta) '(Gcolonna$,Gpt)
  SELECT PEEK(@Gcolonna$+punta)
    CASE _"1"
      POKE @Gcolonna$+punta,_"X"
    CASE _"X"
      POKE @Gcolonna$+punta,_"2"
    CASE _"2"
      LONG IF punta < 13
        POKE @Gcolonna$+punta,_"1"
        INC(punta)
        FN nuovacolonna(punta)
      END IF
  END SELECT
END FN

STAZ ~)~


I wonder if you really need to be using asm. Sometimes a different approach can help.

Here is a tiny little FB function that does the same thing as yours. It probably can't compete with asm, but on my machine your code took 226 ticks for 100,000 iterations. This code took 53. 8)

Unless another 15% increase in speed is essential, why mess with it?

COMPILE 0,_macsbuglabels
GLOBALS
Gcolonna$ = "1111111111111"
DEFSTR LONG
g2X1& = _"2X1 "
END GLOBALS

LOCAL FN nuovacolonna(punta)
  t = PEEK(@Gcolonna$ + punta) AND 3
  POKE @Gcolonna$ + punta,PEEK(@g2X1& + t)
  LONG IF t = 2
    LONG IF punta < 13
      FN nuovacolonna(punta + 1)
    XELSE
      POKE @Gcolonna$ + 13, 50
    END IF
  END IF
END FN

This code may be very hard to understand, but if it works fast, who cares? It does work because when you AND the ascii values of "X", "1", and "2" with 3, you get 0, 1, and 2. Use these as lookups for the three replacement bytes stored in g2X1&. Then, for the single case where you don't want a replacement (former value = 2 and punta = 13), just go back and fix it! That case is rare enough not to slow things down significantly.

Hats off (once again) to Staz! Not only does his code run 45% faster than mine (which I thought was fast), it maintains the clarity of Alessandro's original and avoids the assumptions I made which might not be true (like punta will only have values of 1 to 13).

I've learned a lot from this exchange. Now I wonder what is the purpose of this blazing piece of code. It _looks_ like something for a card game.

Jay Reeve