Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Logical Bitwise Functions - AND, OR, XOR, NOT
#1
These items do seem to be quite high on a few people's wish list. I hope they help!

Right now I only know how to use FASTCALL with a single parameter. If anyone knows how standard multi parameter calls work when we get into m/c please let me know. For the moment, these work and are pretty fast, even though AND and OR cheat a little.

Binary NOT (8 bit version)
Code:
FUNCTION FASTCALL bNOT (sentIn as uByte) as uByte
    asm
    CPL
    end asm
END FUNCTION

USAGE: bNOT(byte value or ubyte value)

Binary NOT (16 bit version)
Code:
FUNCTION FASTCALL bNOT (sentIn as uInteger) as uInteger
    asm
    LD a,h
    CPL
    ld h,a
    ld a,l
    CPL
    ld l,a
    end ASM
END FUNCTION

USAGE: bNOT(uInteger value)

How about this as a compromise: A NOT function that does an 8 bit not for any value that fits in 8 bits, a 16 bit NOT for any value that fits in 16 bits, and a 32 bit NOT for any larger value.

Code:
FUNCTION FASTCALL bNOT(sentIn as uLONG) as uLONG
    asm

    LD A,D    
    OR E
    JR Z,word  ; if DE = 0, assume it's NOT a long!
    LD A, D
    CPL
    LD D, A
    LD A,E
    CPL
    LD E,A

word:
    LD A,H
    AND A      ; if H=0 assume it's not 16 bit.
    JR Z, byte
    CPL
    LD H,A

byte:
    LD A,L
    CPL
    LD L,A

    END asm

END Function



Binary AND (8 bit)
Code:
FUNCTION bAND (byte1 as uByte, byte2 as uByte) as uByte
       return bANDHL(byte1*256+byte2)
END function

FUNCTION FASTCALL  bANDHL (HL as uInteger) as uByte
    asm
    LD a,h
    AND l
    end asm
END FUNCTION

USAGE bAND (byte value1, byte value2)
NOTE: Yes, this is one function that calls another. It cheats by putting two 8 bit values into a 16 bit. It's definitely possible to have something better optimized, and if I learn how standard calls work, I'll use that.
In the meantime, this does work.

Binary OR (8 bit)
NOTE: This uses the same sneaky methods as bAND. I'm sure better code will turn up later.
Code:
FUNCTION bOR (byte1 as uByte, byte2 as uByte) as uByte
      return bORHL(byte1*256+byte2)
END function

FUNCTION FASTCALL bORHL (HL as uInteger) as uByte
    asm
    LD a,h
    OR l
    end asm
END FUNCTION
USAGE bOR(byte value,byte value)
Reply
#2
Nice! Even if I do not understand how it works, it will help me until BAND, BOR and BNOT are completly implemented by Boriel. Thanks! I had a completly different way to do it until now.
------------------------------------------------------------
http://lcd-one.da.ru redirector is dead
Visit my http://members.inode.at/838331/index.html home page!
Reply
#3
Glad you like them, LCD.

How they work? Well, since the Z80 processor has instructions to do bitwise AND/OR/NOT - they basically pull the numbers from ZX basic into a machine code form, get the processor to do that bitwise function it knows how to do on them, and then works them back into ZX basic for you.

The actual bitwise instruction is only one line in each case - the bit that does the actual job is AND/OR/CPL (for and,or, not).

When Boriel implements them fully, I guarantee his code isn't going to be a long way from what I have here. (In fact, if anyone can do an 8 bit NOT in LESS than one line of assembly, I'd be really impressed Smile )

Lion
Reply
#4
In fact I wondered how they work with Fastcall.
Do Fastcall get the argument (sentin) as A (Accumulator) value if argument is ubyte, and HL if it is uinteger?
Why CPL and not NOT?
bANDHL doea a binary AND of L and A?
I'm a little bit confused...

And whai I mean: Boriels functions would support 1,2, and 4 byte wide variables, I hope at least

LCD
------------------------------------------------------------
http://lcd-one.da.ru redirector is dead
Visit my http://members.inode.at/838331/index.html home page!
Reply
#5
> Do Fastcall get the argument (sentin) as A (Accumulator) value if argument is ubyte, and HL if it is uinteger?

Exactly right. You're allowed one thing sent in with fastcall - a byte arrives as A and a 16 bit value arrives as HL. For that matter a LONG arrives as DEHL.

Sending out works the same way. A byte return has to be in A, and an Integer return has to be in HL.

Let's talk about AND:

bAND (byte1, byte2) gets two bytes as a standard ZX BASIC function.

It puts them BOTH into a uinteger and sends them to a fastcall. In effect it puts them in HL. It makes H = byte1 and L=Byte 2.

bANDHL does (H AND L) effectively. But there's no z80 assembler option to do that, we can only AND A with something.

so it copies H into A, and then AND's A with L; which is the same as (H AND L) effectively.

NOT:
The z80 assembly instruction CPL (which stands for 'complement') swaps all the 1's for 0's and all the 0's for 1's - it's a binary NOT basically. There is no z80 assembly instruction called 'NOT' - but this one means the same thing in this case. Doing this is one way of making a number negative in binary. It's a little technical, but you could look at wikipedia for more on that:

<!-- m --><a class="postlink" href="http://en.wikipedia.org/wiki/Signed_number_representations#Ones.27_complement">http://en.wikipedia.org/wiki/Signed_num ... complement</a><!-- m -->

I think I've worked out how to use standard call now as well. So, I think I might be able to do a function that does it all. Still need to work out how return values on things like Long integers work though. It's probably the stack. Also what happens if you send bNOT (uByte) to a function expecting bAND(Long)? What would you want it to do?

I have a question: What are you using this for? What do you need LONG AND to work with that wouldn't work with byte size chunks?


Oh: In the spirit of trying to get everything better documented, I added documentation for FASTCALL to the wiki: <!-- m --><a class="postlink" href="http://www.boriel.com/wiki/en/index.php/ZX_BASIC:FastCall">http://www.boriel.com/wiki/en/index.php ... C:FastCall</a><!-- m -->

I've been adding bits to the wiki command page as time goes by and I needed to work something out.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)