Thread Rating:
  • 1 Vote(s) - 5 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Tutorial: How to put inline assembly functions into ZX Basic
#1
Finally finished this, and got it working.

http://goo.gl/Iw32U
Reply
#2
Hey!!! Amazing!! Thanks! 8)
Reply
#3
I never got around to learning assembly, Smile
Reply
#4
Well, I'm recommending ZX Basic as a way of learning - you can do it a little bit at a time, rather than having to do everything in assembly.
Reply
#5
Do you allow me to put a Copy of this cool Doc in Spectrum profi Club magazine? Big Grin
------------------------------------------------------------
http://lcd-one.da.ru redirector is dead
Visit my http://members.inode.at/838331/index.html home page!
Reply
#6
Of course, LCD. If you can make it look better formatted!
Reply
#7
britlion Wrote:Of course, LCD. If you can make it look better formatted!
Thanks! Sure I will reformat it, thats no problem!

Edit: By the way, sorry for being off topic, but I did my mirroring function in Boriels BASIC a little bit different (without a table):
Code:
function mirror(dowedoit as ubyte, number as ubyte) as ubyte
    dim result as ubyte
    if dowedoit then
        result=(number&1)<<7|(number&2)<<5|(number&4)<<3|(number&8)<<1|(number&16)>>1|(number&32)>>3|(number&64)>>5|(number&128)>>7
    Else
        result=number
    end if
    return result
end Function
Anyway, optimising the routines is not the topic here. Your tutorial is great!
------------------------------------------------------------
http://lcd-one.da.ru redirector is dead
Visit my http://members.inode.at/838331/index.html home page!
Reply
#8
Yes - that looks like it would work, but it's a LOT harder to understand. I deliberately kept it as easy to read for Sinclair Basic users as possible, such as keeping "REM" rather than ' and using LET everywhere...

Also stuck to using BAND rather than & - and the basic and the machine code use very very nearly the same algorithm, so it's easier to see what the assembly is using.
Reply
#9
britlion Wrote:Yes - that looks like it would work, but it's a LOT harder to understand. I deliberately kept it as easy to read for Sinclair Basic users as possible, such as keeping "REM" rather than ' and using LET everywhere...

Also stuck to using BAND rather than & - and the basic and the machine code use very very nearly the same algorithm, so it's easier to see what the assembly is using.

Thats why I wrote its off Topic. Thats my art of coding, hard to understand, not suitable for tutorials, but working and very fast.
Wink
I do not use the LET command, but you are right, BAND is easier to understand for novices than &, I just used it because it is shorter and fits better in a line of code.
You inspired me to learn a bit more assembly.
------------------------------------------------------------
http://lcd-one.da.ru redirector is dead
Visit my http://members.inode.at/838331/index.html home page!
Reply
#10
You should see what I'm working on now. Probably way too ambitious to finish. But I did 12 pages this evening...

http://goo.gl/4jPd5
Reply
#11
LCD Wrote:
Code:
function mirror(dowedoit as ubyte, number as ubyte) as ubyte
    dim result as ubyte
    if dowedoit then
        result=(number&1)<<7|(number&2)<<5|(number&4)<<3|(number&8)<<1|(number&16)>>1|(number&32)>>3|(number&64)>>5|(number&128)>>7
    Else
        result=number
    end if
    return result
end Function
Though if I was going to, I'd say why bother with a new variable? :mrgreen:

Code:
function mirror(dowedoit as ubyte, number as ubyte) as ubyte
   if dowedoit then
      number=(number&1)<<7|(number&2)<<5|(number&4)<<3|(number&8)<<1|(number&16)>>1|(number&32)>>3|(number&64)>>5|(number&128)>>7
   end if
   return number
end Function

That said, if you read the behemoth assembly that makes. Ouch. Hopping on and off the stack like crazy! Not to mention a lot of very expensive reads and writes to (IX+7) - which cost 19 T states each. I wonder if my original beginners algorithm is faster!

Anyway, I think my suggested optimized version is pretty tight:

Code:
function fastcall mirror (dowedoit as uByte, number as uByte) as uByte
asm
   pop hl
   pop bc
   AND A
   LD A,B
   RET Z
   ld b,8
   ld c,a
   XOR A
        
   mirrorLoop:
      RR C
      RLA  
   DJNZ mirrorLoop
   jp (hl)        
end asm
END FUNCTION
Reply
#12
I was in fact planning an ebook (PDF free & hard cover), for ZX Basic compiler. Big Grin
But it's a huge task, and English is not my mother tongue! Tongue
Reply
#13
boriel Wrote:I was in fact planning an ebook (PDF free & hard cover), for ZX Basic compiler. Big Grin
But it's a huge task, and English is not my mother tongue! Tongue

Yes. yes it is. Working on it...

At least some of it. No doubt I'll have time shortages again.
Reply
#14
britlion Wrote:
LCD Wrote:
Code:
function mirror(dowedoit as ubyte, number as ubyte) as ubyte
    dim result as ubyte
    if dowedoit then
        result=(number&1)<<7|(number&2)<<5|(number&4)<<3|(number&8)<<1|(number&16)>>1|(number&32)>>3|(number&64)>>5|(number&128)>>7
    Else
        result=number
    end if
    return result
end Function
Though if I was going to, I'd say why bother with a new variable? :mrgreen:

Code:
function mirror(dowedoit as ubyte, number as ubyte) as ubyte
   if dowedoit then
      number=(number&1)<<7|(number&2)<<5|(number&4)<<3|(number&8)<<1|(number&16)>>1|(number&32)>>3|(number&64)>>5|(number&128)>>7
   end if
   return number
end Function

That said, if you read the behemoth assembly that makes. Ouch. Hopping on and off the stack like crazy! Not to mention a lot of very expensive reads and writes to (IX+7) - which cost 19 T states each. I wonder if my original beginners algorithm is faster!
:oops:
I overseen it... It was my mirroring function from my unfinished fractal picture decompressor which I adopted to match yours, mine had no dowedoit, so it was:
Code:
function MirrorByte(num as ubyte) as ubyte
    return (num&1)<<7|(num&2)<<5|(num&4)<<3|(num&8)<<1|(num&16)>>1|(num&32)>>3|(num&64)>>5|(num&128)>>7
end function
Your original beginners function was not faster, it was in fact slower because multiplication and division is allways slower than bitshifting. I'm happy that boriel included it as it is a big help in optimizing programs, so you could use SHR and SHL in place of >> and <<. With this your code will match the ASM version much better, and work faster.
britlion Wrote:Anyway, I think my suggested optimized version is pretty tight:

Code:
function fastcall mirror (dowedoit as uByte, number as uByte) as uByte
asm
   pop hl
   pop bc
   AND A
   LD A,B
   RET Z
   ld b,8
   ld c,a
   XOR A
        
   mirrorLoop:
      RR C
      RLA  
   DJNZ mirrorLoop
   jp (hl)        
end asm
END FUNCTION
It is!!!
Much faster than both compiled codes.

The books looks very good by the way!!! My compliments!
------------------------------------------------------------
http://lcd-one.da.ru redirector is dead
Visit my http://members.inode.at/838331/index.html home page!
Reply
#15
Ah - then you'd need one that just looks like this, I think:


Code:
function fastcall mirror (number as uByte) as uByte
asm
   ld b,8
   ld c,a
   XOR A
mirrorLoop:
      RR C
      RLA
DJNZ mirrorLoop
end asm
END FUNCTION

I haven't tested it, mind. Just typed it here. Feels right, though Smile
Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)