Help me understand the use of 'AND' here

The place for codemasters or beginners to talk about programming any language for the Spectrum.
Post Reply
User avatar
chilledgamer
Dizzy
Posts: 63
Joined: Wed Jun 24, 2020 1:22 am
Location: Torquay
Contact:

Help me understand the use of 'AND' here

Post by chilledgamer »

Hi all. I've made lots of progress in my z80 asm coding adventure. One thing that I am slightly confused about still (even after reading two books fully several times over) is the use of 'AND n' as a way to "keep a value within n".

I completely understand using 'AND %00000111' for example to mask out the highest 5 bits, but many examples in the books seem to use it as a means of 'modulo' or something similar (ie. getting a larger number to fit within a smaller number).

Here are some examples from books:

Code: Select all

; Simple pseudo-random number generator.
; Steps a pointer through the ROM (held in seed), returning
; the contents of the byte at that location.
random ld hl,(seed) ; Pointer
ld a,h
and 31 ; keep it within first 8k of ROM. ;;<- THIS LINE
ld h,a
ld a,(hl) ; Get "random" number from location.
inc hl ; Increment pointer.
ld (seed),hl
ret
seed defw 0

Code: Select all

yx2pix:		;don't worry about how this works yet! just arrive with arrive with B=y 0-192, C=x 0-255
	ld a,b	;return with DE at corresponding place on the screen
	rra
	rra
	rra
	and %00011000
	or %01000000
	ld d,a
	ld a,b
	and 7 ;; <--- THIS LINE
	or d
	ld d,a
	ld a,b
	rla
	rla
	and %11100000
	ld e,a
	ld a,c
	rra
	rra
	rra
	and %00011111
	or e
	ld e,a
	ret
As you can see in the first example, he uses the bold line to keep the value in a (loaded into h immediately afterwards) within '31'. Two parts of that line confuse me! a) does this have bias on larger numbers (ie. if a>=31; AND 31 would always equal 31 ???)? b) why is the value '31' used anyway, to get the first 8k of ROM i mean?

So those two parts confuse me still, then on to the next example. This one slightly more simple for me, I think I realise he uses value 7 because each screen character has 8 lines (0-7), so again he wants to take a high number and reduce it to a number equal or less to 7. Thing that confuses me is yet again, is this biased top heavy? doesn't 'AND 7' just mean that anything above 7 will equal 7? (NOTE: I think i do realise that in this yx2pix function he immediately uses 'OR D' which more than likely is where the formula gets the modulo of the division. But that could be completely wrong, I am badly confused lol.

I have seen other examples of 'AND n' being used to keep numbers within 0-n , every single time I have just used them and not worried too much of how they work, but now I am trying to implement a random spawn function of my own, and the result i have so far doesnt seem very random (in fact there is a distinct pattern in how they are spawned)

(for context, I am trying to build a road scene a' la Horace Goes Skiing. So I am trying to spawn cars on left side of screen at random intervals also with random y position offsets)
User avatar
utz
Microbot
Posts: 116
Joined: Wed Nov 15, 2017 9:04 am
Contact:

Re: Help me understand the use of 'AND' here

Post by utz »

chilledgamer wrote: Sun Jul 05, 2020 3:05 pm a) does this have bias on larger numbers (ie. if a>=31; AND 31 would always equal 31 ???)?
No. A logical AND operates on individual bits. The result of ANDing two bits is 1 if and only if both of the pair of bits are 1.

Code: Select all

    %00110001    (= 49 decimal)
AND %00000111    (= 7 decimal)
=========================
=   %00000001
chilledgamer wrote: Sun Jul 05, 2020 3:05 pm b) why is the value '31' used anyway, to get the first 8k of ROM i mean?
Look at the value 31 in binary, and use the above example to work out why ;)
User avatar
chilledgamer
Dizzy
Posts: 63
Joined: Wed Jun 24, 2020 1:22 am
Location: Torquay
Contact:

Re: Help me understand the use of 'AND' here

Post by chilledgamer »

I get that it converts all bits to 0 unless both compared bytes had that bit as 1. But why 31, to get "first 8k of ROM"? i don't get it.
I have windows Calculator set to programmers already , so I've been looking at many numbers (including these) in base2, base10 and base16 simultaneously, but this has me stumped in my brain lol
User avatar
chilledgamer
Dizzy
Posts: 63
Joined: Wed Jun 24, 2020 1:22 am
Location: Torquay
Contact:

Re: Help me understand the use of 'AND' here

Post by chilledgamer »

utz wrote: Sun Jul 05, 2020 3:20 pm
chilledgamer wrote: Sun Jul 05, 2020 3:05 pm a) does this have bias on larger numbers (ie. if a>=31; AND 31 would always equal 31 ???)?
No. A logical AND operates on individual bits. The result of ANDing two bits is 1 if and only if both of the pair of bits are 1.

Code: Select all

    %00110001    (= 49 decimal)
AND %00000111    (= 7 decimal)
=========================
=   %00000001
chilledgamer wrote: Sun Jul 05, 2020 3:05 pm b) why is the value '31' used anyway, to get the first 8k of ROM i mean?
Look at the value 31 in binary, and use the above example to work out why ;)

Perhaps it would be helpful to post my attempt at a random spawner function (which makes use of that 'random' function posted above)

Code: Select all

spawncarupper:
    ld b, MAX_VEHICLES
    ld ix,uppervehicles
alivecheck:
    ld a,(ix)
    cp 0
    jr z, spawnit
    ld de, BYTES_PER_VEHICLE
    add ix,de
    djnz alivecheck
    ret
spawnit:
    ld a,1
    ld (ix),a ; set isalive to 1 for this car
    call random ;set a to random number
    and TOTAL_VEHICLE_TYPES
    ld (ix+2),a ;set random vehicle TOTAL_VEHICLE_TYPES
    call random ;set a to rand number
    ld a, UPPER_LANE_X
    ld (ix+3), a ;set pos x to correct position
    call random
    ;add a, UPPER_LANE_Y ; add the upperlane y base point
    ld (ix+4),a ;set pos y
    ret
As per screenshot, it almost always looks like this (ignore the fact that some sprites facing left, they are moving right):


Image

NOTE: There is meant to be 3 vehicle variants, but some reason only 0 and 2 of the vehicles are chosen. Also the y offset seems always the same every time I compile or run the game
User avatar
utz
Microbot
Posts: 116
Joined: Wed Nov 15, 2017 9:04 am
Contact:

Re: Help me understand the use of 'AND' here

Post by utz »

"8K" = 8192 bytes. So the first "8K of ROM" means an address between 0 and 8191. 8191 = %11111 11111111, or 0x1fff. We don't need to worry about the lower 8 bits, since they may take any value. The upper 8 bits on the other hand must have a value between 0 - %11111, or 0 - 0x1f, or 0 - 31 in decimal. Hence the AND 31.
User avatar
chilledgamer
Dizzy
Posts: 63
Joined: Wed Jun 24, 2020 1:22 am
Location: Torquay
Contact:

Re: Help me understand the use of 'AND' here

Post by chilledgamer »

thank you so much dude. I get it now :D (Sadly that part was glossed over in the books, unless I somehow missed the detailed explanations)

Well, now I know that the AND was being used as I thought it was, then i just have to try to figure out why my own spawner function is not seeming random, and is only selecting sprite index 0,2 (ie. ignoring 1). As far as I could tell, 'call random' gives me a number 00-ff in a, then I do AND 2 (which I am hopeing changes a to equal 0,1,2 -for some reason it isn't ever 1)

Same applies with the y positioning, why is it always the same value?? -perhaps this RAM step random technique is getting the same data from 'seed' memory address every time.

Well, sadly I have to go in about half hour but if I am not too tired I will be trying again later at night. Thanks for your help
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2641
Joined: Mon Nov 13, 2017 3:16 pm

Re: Help me understand the use of 'AND' here

Post by Ast A. Moore »

chilledgamer wrote: Sun Jul 05, 2020 3:26 pm I get that it converts all bits to 0 unless both compared bytes had that bit as 1. But why 31, to get "first 8k of ROM"? i don't get it.
The masked value then gets passed into H, which is the high byte of the address. So, it is effectively limited to a range of 0–$1f. The full address will then be (at it’s upper limit): $1fff, or 8191 in decimal—exactly the first 8K (8 × 1024) of the ROM address space.

A useful way of thinking of using AND in this manner is truncation: you literally truncate (chop off) the extra bits of a number. So, while the highest 16-bit number ($ffff) is 1111 1111 1111 1111, if you AND the high byte with 31 ($1f), you’ll effectively limit it to 0001 1111 1111 1111, or $1fff (8191).

Make sense now?
Every man should plant a tree, build a house, and write a ZX Spectrum game.

Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
User avatar
chilledgamer
Dizzy
Posts: 63
Joined: Wed Jun 24, 2020 1:22 am
Location: Torquay
Contact:

Re: Help me understand the use of 'AND' here

Post by chilledgamer »

Ast A. Moore wrote: Sun Jul 05, 2020 3:47 pm
chilledgamer wrote: Sun Jul 05, 2020 3:26 pm I get that it converts all bits to 0 unless both compared bytes had that bit as 1. But why 31, to get "first 8k of ROM"? i don't get it.
The masked value then gets passed into H, which is the high byte of the address. So, it is effectively limited to a range of 0–$1f. The full address will then be (at it’s upper limit): $1fff, or 8191 in decimal—exactly the first 8K (8 × 1024) of the ROM address space.

A useful way of thinking of using AND in this manner is truncation: you literally truncate (chop off) the extra bits of a number. So, while the highest 16-bit number ($ffff) is 1111 1111 1111 1111, if you AND the high byte with 31 ($1f), you’ll effectively limit it to 0001 1111 1111 1111, or $1fff (8191).

Make sense now?
It certainly does. I had kinda thought it was like this already but when I tried to do the math I couldnt get it to add up until utz's comments opened the curtains in my brain lol

I am still struggling to see why my values are not random, but that is a challenge I might be able to figure out myself eventually
AndyC
Dynamite Dan
Posts: 1419
Joined: Mon Nov 13, 2017 5:12 am

Re: Help me understand the use of 'AND' here

Post by AndyC »

chilledgamer wrote: Sun Jul 05, 2020 3:44 pm As far as I could tell, 'call random' gives me a number 00-ff in a, then I do AND 2 (which I am hopeing changes a to equal 0,1,2 -for some reason it isn't ever 1)
You have to think in binary. 2 has the bit pattern 0010, so ANDing any value with 2 can only ever return the values 0 or 2.
User avatar
chilledgamer
Dizzy
Posts: 63
Joined: Wed Jun 24, 2020 1:22 am
Location: Torquay
Contact:

Re: Help me understand the use of 'AND' here

Post by chilledgamer »

AndyC wrote: Sun Jul 05, 2020 3:58 pm
chilledgamer wrote: Sun Jul 05, 2020 3:44 pm As far as I could tell, 'call random' gives me a number 00-ff in a, then I do AND 2 (which I am hopeing changes a to equal 0,1,2 -for some reason it isn't ever 1)
You have to think in binary. 2 has the bit pattern 0010, so ANDing any value with 2 can only ever return the values 0 or 2.
This must be it! Thanks!

I will try to figure out how to do the numbers properly. Thank you all
User avatar
chilledgamer
Dizzy
Posts: 63
Joined: Wed Jun 24, 2020 1:22 am
Location: Torquay
Contact:

Re: Help me understand the use of 'AND' here

Post by chilledgamer »

Just for the record, and in case any other poor soul is having a similar problem in the future. I solved the number of vehicle variants as follows.

Instead of 'AND 2' to get the value to be between 0-2. I needed to use 'AND %00000011'.

Otherwise, as stated above, the only possible outcomes from AND 2 is either "%00000000" or "%00000010"
User avatar
1024MAK
Bugaboo
Posts: 3129
Joined: Wed Nov 15, 2017 2:52 pm
Location: Sunny Somerset in the U.K. in Europe

Re: Help me understand the use of 'AND' here

Post by 1024MAK »

When using bitwise operators (which is only what the Z80 does) you always have to think in binary.
Put the variable number you are using in binary,
Then below it and lined up with it put the fixed number again in binary
Now look at all the possible results that are possible on the next line.

So:

Code: Select all

76543210 - bit number

11111111 - variable number, in this case 255
00000010 - fixed number = 2
———————— AND
00000000 = 0, first possible number 
00000010 = 2, second possible number, and with a variable number of 255,
              this is the result returned.
In this case, that’s the total number of possible outcomes, hence why you never get 3.

Mark
:!: Standby alert :!:
“There are four lights!”
Step up to red alert. Sir, are you absolutely sure? It does mean changing the bulb :dance
Looking forward to summer later in the year.
User avatar
1024MAK
Bugaboo
Posts: 3129
Joined: Wed Nov 15, 2017 2:52 pm
Location: Sunny Somerset in the U.K. in Europe

Re: Help me understand the use of 'AND' here

Post by 1024MAK »

chilledgamer wrote: Sun Jul 05, 2020 4:13 pm Just for the record, and in case any other poor soul is having a similar problem in the future. I solved the number of vehicle variants as follows.

Instead of 'AND 2' to get the value to be between 0-2. I needed to use 'AND %00000011'.

Otherwise, as stated above, the only possible outcomes from AND 2 is either "%00000000" or "%00000010"
Yes. Don’t forget that a microprocessor is just a big bunch of logic gates. See the Wikipedia page for an AND gate.

In the Z80 ALU, circuitry working like a bunch of AND gates does the operation.

Mark
:!: Standby alert :!:
“There are four lights!”
Step up to red alert. Sir, are you absolutely sure? It does mean changing the bulb :dance
Looking forward to summer later in the year.
User avatar
PeterJ
Site Admin
Posts: 6901
Joined: Thu Nov 09, 2017 7:19 pm
Location: Surrey, UK

Re: Help me understand the use of 'AND' here

Post by PeterJ »

This is such an interesting thread. Thank you!
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2641
Joined: Mon Nov 13, 2017 3:16 pm

Re: Help me understand the use of 'AND' here

Post by Ast A. Moore »

1024MAK wrote: Sun Jul 05, 2020 4:28 pm In the Z80 ALU, circuitry working like a bunch of AND gates does the operation.
Not strictly related to the topic, but curious nonetheless: the Z80 ALU is actually 4-bit.

(But I’m sure you know this already.)
Every man should plant a tree, build a house, and write a ZX Spectrum game.

Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
User avatar
1024MAK
Bugaboo
Posts: 3129
Joined: Wed Nov 15, 2017 2:52 pm
Location: Sunny Somerset in the U.K. in Europe

Re: Help me understand the use of 'AND' here

Post by 1024MAK »

Ast A. Moore wrote: Sun Jul 05, 2020 5:52 pm
1024MAK wrote: Sun Jul 05, 2020 4:28 pm In the Z80 ALU, circuitry working like a bunch of AND gates does the operation.
Not strictly related to the topic, but curious nonetheless: the Z80 ALU is actually 4-bit.

(But I’m sure you know this already.)
Yep, that’s why I was vague and said “bunch”, in order not to confuse things :lol:
It’s thought to be one of the reasons for the relatively high clock rate compared to its rival MPUs.

Mark
:!: Standby alert :!:
“There are four lights!”
Step up to red alert. Sir, are you absolutely sure? It does mean changing the bulb :dance
Looking forward to summer later in the year.
XoRRoX
Manic Miner
Posts: 233
Joined: Wed Jul 11, 2018 6:34 am

Re: Help me understand the use of 'AND' here

Post by XoRRoX »

Thanks for the OP of posting the question and contributors to explain.

I'm quite amazed that debuggers in emulators do not display values in binary.
AndyC
Dynamite Dan
Posts: 1419
Joined: Mon Nov 13, 2017 5:12 am

Re: Help me understand the use of 'AND' here

Post by AndyC »

XoRRoX wrote: Sun Jul 05, 2020 9:29 pm I'm quite amazed that debuggers in emulators do not display values in binary.
One of the reasons most assembly programmers tend to use hex is because it is very easy to visualise the bit patterns without having to have them written out in full, unlike decimal where you basically have to do the maths to convert it into the binary representation.
XoRRoX
Manic Miner
Posts: 233
Joined: Wed Jul 11, 2018 6:34 am

Re: Help me understand the use of 'AND' here

Post by XoRRoX »

AndyC wrote: Sun Jul 05, 2020 10:17 pm
XoRRoX wrote: Sun Jul 05, 2020 9:29 pm I'm quite amazed that debuggers in emulators do not display values in binary.
One of the reasons most assembly programmers tend to use hex is because it is very easy to visualise the bit patterns without having to have them written out in full, unlike decimal where you basically have to do the maths to convert it into the binary representation.
I'm quite new to assembly but understand that with addresses it's helpful to use hex.
I'm not quite understanding how it'd be helpful for binary.

Could you give some examples, please?
User avatar
1024MAK
Bugaboo
Posts: 3129
Joined: Wed Nov 15, 2017 2:52 pm
Location: Sunny Somerset in the U.K. in Europe

Re: Help me understand the use of 'AND' here

Post by 1024MAK »

So, it at first appears rather complex. Especially when people are constantly jumping from decimal to hexadecimal and then sprinkle in some octal or binary.

One thing to remember, humans only use decimal because at some point in the past, somehow someone came up with that idea and it long ago stuck.

But binary, octal, hexadecimal all work the same. Only major difference is the number of different symbols/characters used.

In decimal we use “0”, “1”, through to “9”. If we have 9 and add 1, because we have run out of symbols, a carry takes place and then we write “10”. The other number systems work exactly the same, the difference being binary only uses two symbols, octal only uses eight symbols and hexadecimal uses sixteen symbols.

Now digital logic circuits only have two valid states per line (or input pin or output pin or node). They are logic low, also called logic zero. And logic high, also called logic one. Hence why binary is the most relevant number system to use when representing the actual logic circuits.

But binary is not easy for humans to work with, it’s bad enough with eight bit (byte) values, but with sixteen or thirty-two bits, it just becomes a mass of 0’s and 1’s and humans get muddled and silly errors are the result.

So to make life easier, a compromise had to be found, as conversion between binary and decimal is not very easy to do in your head. That compromise was originally octal. But later hexadecimal became the preferred method.

So why hexadecimal?

Because the sixteen symbols are not too hard to convert to a four bit binary value. A number made up of two hexadecimal digits can represent one eight bit byte. Four hexadecimal digits can represent one sixteen bit word, which is convenient for the address range on a Z80, 6502, or other 8 bit microprocessor.

And using hexadecimal is much easier when writing code, or discussing code with other humans.

Until (if) you get used to doing the conversion in your head, a table can help:

Code: Select all

Hex - binary
 0 = 0000
 1 = 0001
 2 = 0010
 3 = 0011
 4 = 0100
 5 = 0101
 6 = 0110
 7 = 0111
 8 = 1000
 9 = 1001
 A = 1010
 B = 1011
 C = 1100
 D = 1101
 E = 1110
 F = 1111

Don’t worry if you can’t remember or can’t do the conversion in your head, just use a table.

So now with hexadecimal, why do you need to still use binary, after all, all the hardware was designed long ago...

Well, when using assembler, you are instructing the Z80 microprocessor unit (MPU) in a human friendly version of machine code. The MPU operates only using binary. The hardware that the MPU communicates with only uses binary.

So when you get the MPU to read say, the keyboard or say a Kempston joystick port, you may only want five of the eight bits of the eight bit byte. The remaining three bits are of no interest. And as some of them may be different values between reads of the hardware (because they are either unused and are “floating” or because they are used for different functions or there are differences between different hardware versions), you cannot rely on them being in a dependable known state (value).

A logical AND operation can ‘mask’ off the bits of the byte that you want, setting the unwanted bits to a known zero state (value). That then makes the following assembly code much easier. And working out what you want to do with individual or groups of bits is much easier if you work in binary ;)

I hope that helps :D

Mark
Last edited by 1024MAK on Mon Jul 06, 2020 10:29 am, edited 3 times in total.
:!: Standby alert :!:
“There are four lights!”
Step up to red alert. Sir, are you absolutely sure? It does mean changing the bulb :dance
Looking forward to summer later in the year.
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2641
Joined: Mon Nov 13, 2017 3:16 pm

Re: Help me understand the use of 'AND' here

Post by Ast A. Moore »

A quick (and obvious) shortcut to help you asses a binary number by just looking at a hexadecimal (or decimal) one is the fact that odd numbers end in 1 and even numbers in 0. Can be useful sometimes.
Every man should plant a tree, build a house, and write a ZX Spectrum game.

Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
User avatar
utz
Microbot
Posts: 116
Joined: Wed Nov 15, 2017 9:04 am
Contact:

Re: Help me understand the use of 'AND' here

Post by utz »

It's especially helpful in cases like the one you were struggeling with with "and 31" and "first 8K of ROM". The decimal numbers 31 and 8191 tell you nothing. 0x1f and 0x1fff on the other hand immediately let you see that you don't need to worry about the low byte.

Or take PeterJ's question here, where I suggested "and 56". I used decimal because that's what he was using, but had I said "0x38" instead, it would've been immediately obvious that this has the desired effect of masking the lower three bits.
User avatar
Morkin
Bugaboo
Posts: 3285
Joined: Mon Nov 13, 2017 8:50 am
Location: Bristol, UK

Re: Help me understand the use of 'AND' here

Post by Morkin »

It's weird, I've always avoided hex and stuck to decimal - I think this is after years of mucking around with graphics and calculating values manually so I've got to grips with recognising patterns quite quickly, stuff like 129 (top and bottom bits set), 240 (top 4 bits), and then 120, 60, 30, as it shifts right, and loads of others.

It was only in recent years when I saw the value of hex and splitting this into 2 sets of 4 bits, but I decided it was probably too late by then to change (old dogs & all that... ;)). One big advantage seems to be with 16 bit numbers, but I've not been overly concerned with working out where things are in 256 byte data banks very often.
My Speccy site: thirdharmoniser.com
Post Reply