Re: Woz range check code explanation?
From: Michael Beck (spamtrap_at_crayne.org)
Date: 11/11/04
- Next message: PercyP: "Re: outputting more than 25 lines. How?"
- Previous message: J. Voss: "Re: AT&T to Intel Syntax Translation"
- In reply to: Jim Leonard: "Woz range check code explanation?"
- Next in thread: Jim Leonard: "Re: Woz range check code explanation?"
- Reply: Jim Leonard: "Re: Woz range check code explanation?"
- Reply: C : "Re: Woz range check code explanation?"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: Thu, 11 Nov 2004 18:23:33 +0000 (UTC)
Jim Leonard wrote:
Ok, for those who care here the complete explanation of the code:
>
> This checks if a value is within one of two subranges N1...N2 or
> N3...N4.
>
> ; Test range N1 through N2
> eor #N1 ; Make low range start at 0
> cmp #(N2-N1)+1 ; Test low range valid
> bcc valid ; Valid low range
>
> ; Test range N3 through N4
> adc #$FE - ( N4 eor N1 ) ; Make high range end at $FF
> cmp #$FF - ( N4 - N3 ) ; Test high range validity
> bcc error ; Invalid high range
> and #$0F ; Restore true hex value
> valid:
>
> Note that the #$FE is actually #$FF since CF is set.
>
> To use this to check for valid ASCII hex digits and convert them to
> binary hex:
>
> N1 = $30, N2 = $39, N3 = $41, N4 = $46
>
> eor #$30
> cmp #$0A
> bcc valid
> adc #$88 ; ( = $89 - clc )
> cmp #$FA
> bcc error
> and #$0F
> valid:
>
> (I still rate this as one of the neatest asm hacks I've ever seen).
This code uses the following "Trick" to do a range change with ONE compare:
if N1 <= N2
N1 <= a <= N2 <==> a - N1 <u= N2-N1 <==> a - N1 <u N2-N1+1
Note that the second <= must be an unsigned compare (using the CARRY flag on
6502). It works even if a underflow occurs. A proof can be found in teh
excelent book "Hacker's Delight" by Henry S. Warren.
The 6502 did not have a SUB instructions, just a SBB (sub with borrow) which
would requiere an SEC (set CARRY) if the state of the carry flag is not
known to be set.
To save this instruction, Steve used an EOR which works because N1 is 0x30,
so:
a ^ 0x30 == a - 0x30 for the lowest 4 bit.
because N2 is 0x39, the difference is 9 which fits into the "right" 4 bit.
The second test uses a similiar trick:
if N3 <= N4
N3 <u= a <u= N4 <==>
N3 + (MAX-N4) <u= a + (MAX-N4) <u= N4 + (MAX-N4) <==>
N3 + (MAX-N4) <u= a + (MAX-N4) <u= MAX <==>
N3 + (MAX-N4) <u= a + (MAX-N4)
MAX is the highest unsigned value, so the test a + (MAX-N4) <u= MAX
is always true and can be omitted. For 8 bit values, MAX is 0xFF.
Before we use that we must correct the effect of the EOR.
To do this, the "right" range is now N3 ^ N1 ... N4 ^ N1, in our case
0x11 .. 0x16. Again, this works only, because the difference between N3 and
N4 is less than 4 bit, so the EOR transform the interval uniformly.
(Or more precisely, N3 AND N1 == N4 AND N1, so the EOR changes the same
bits).
Now we add #$FF - ( N4 eor N1 ) which is #$E9, so the code must be
adc #$E8
this transforms the range into 0xFA .. 0xFF. Using the wrap around
we know that it is sufficient to test the lower border.
So, this 2 range checks works only if:
N1 is of the form xxx0..0
N2 - N1 < 10..0 (same number of zeros as above)
N4 AND N1 == N3 AND N1
And all this to save just the SEC :-) Ah, the old times ...
Returning to x86:
The following works for any range N1..N2, N3..N4:
for one range check the following code is the best
sub al, N1
cmp al, (N2-N1)+1
for more range checks do
add al, N1-N3
cmp al (N4-N3)+1
but a xlat may be faster for 2 or more range checks, because you can check
all ranges with one cmp instruction ...
best regards,
-- Michael Beck beck@ipd.info.uni-karlsruhe.de
- Next message: PercyP: "Re: outputting more than 25 lines. How?"
- Previous message: J. Voss: "Re: AT&T to Intel Syntax Translation"
- In reply to: Jim Leonard: "Woz range check code explanation?"
- Next in thread: Jim Leonard: "Re: Woz range check code explanation?"
- Reply: Jim Leonard: "Re: Woz range check code explanation?"
- Reply: C : "Re: Woz range check code explanation?"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|
|