I'm working on a hobby project in 16-bit DOS and trying to figure out
how to do a signed shift left of a 32-bit signed integer in DX:AX. I
have already figured out a signed shift right:
mov cx,bits_to_shift
shift:
sar dx,1 ;signed shr, bit into carry
rcr ax,1 ;rotate carry right
loop @shift
....but I am having the damnest time figuring out how to do a signed
shift left efficiently. If I SAL DX, carry is not brought in. If I
RCL DX, I lose my sign bit.
This is obviously a solved problem; what is the common way of doing
this? I thought of masking the sign bit, grabbing it into a register,
then ORing it to DX when done shifting, but this seems inelegant.
|
|
0
|
|
|
|
Reply
|
Jim
|
2/9/2009 6:56:31 AM |
|
Jim Leonard wrote:
> I'm working on a hobby project in 16-bit DOS and trying to figure out
> how to do a signed shift left of a 32-bit signed integer in DX:AX. I
> have already figured out a signed shift right:
>
> mov cx,bits_to_shift
> shift:
> sar dx,1 ;signed shr, bit into carry
> rcr ax,1 ;rotate carry right
> loop @shift
>
> ...but I am having the damnest time figuring out how to do a signed
> shift left efficiently. If I SAL DX, carry is not brought in. If I
> RCL DX, I lose my sign bit.
>
> This is obviously a solved problem; what is the common way of doing
> this? I thought of masking the sign bit, grabbing it into a register,
> then ORing it to DX when done shifting, but this seems inelegant.
Stop and think for a while and you'll realise that arithmetic left shift
is the same thing as logic left shift.
SAL and SHL are just two names for the same instruction. See the manual.
If a left shift results in an unintentional change of sign, it is due to
an overflow. Try adding a big signed number to itself and watch it
overflow. That's the same thing as shifting it left by one bit, and the
sign changes because the result is too big to be representable.
Bjarni
--
INFORMATION WANTS TO BE FREE
|
|
0
|
|
|
|
Reply
|
Bjarni
|
2/9/2009 3:38:22 PM
|
|
"Jim Leonard" <spamtrap@crayne.org> wrote in message
news:9013cf07-2155-46ba-bcf7-1609df158dc9@f40g2000pri.googlegroups.com...
> I'm working on a hobby project in 16-bit DOS and trying to figure out
> how to do a signed shift left of a 32-bit signed integer in DX:AX. I
> have already figured out a signed shift right:
>
> mov cx,bits_to_shift
> shift:
> sar dx,1 ;signed shr, bit into carry
> rcr ax,1 ;rotate carry right
> loop @shift
>
> ...but I am having the damnest time figuring out how to do a signed
> shift left efficiently. If I SAL DX, carry is not brought in. If I
> RCL DX, I lose my sign bit.
Actually you don't lose the sign bit. A new bit becomes the sign bit and it
will correct Unless the number overflows.
>
> This is obviously a solved problem; what is the common way of doing
> this? I thought of masking the sign bit, grabbing it into a register,
> then ORing it to DX when done shifting, but this seems inelegant.
>
It doesn't even help. OR-ing the sign back onto it will have no effect in
most cases, and when it Does the result will not make sense.
Examples:
0xFFFF : 0xFFFF shifted left by 1:
0xFFFF : 0xFFFE = correct, no OR needed
0x8000 : 0x0000
0x0000 : 0x0000 overflow. but there is no way to fix that. sticking the old
sign in front of it doesn't create a meaningful value.
0x7FFF : 0x0000
0xFFFE : 0x0000 signed overflow. instead of OR-ing you'd need AND-ing, but
even that wouldn't help. 0x7FFE : 0x0000 isn't any more useful to get as an
answer.
|
|
0
|
|
|
|
Reply
|
Harold
|
2/9/2009 4:05:27 PM
|
|
On Feb 9, 8:05�am, "Harold Aptroot" <spamt...@crayne.org> wrote:
> "Jim Leonard" <spamt...@crayne.org> wrote in message
>
> news:9013cf07-2155-46ba-bcf7-1609df158dc9@f40g2000pri.googlegroups.com...
>
> > I'm working on a hobby project in 16-bit DOS and trying to figure out
> > how to do a signed shift left of a 32-bit signed integer in DX:AX. �I
> > have already figured out a signed shift right:
>
> > �mov cx,bits_to_shift
> > shift:
> > �sar dx,1 � � �;signed shr, bit into carry
> > �rcr ax,1 � � � ;rotate carry right
> > �loop @shift
>
> > ...but I am having the damnest time figuring out how to do a signed
> > shift left efficiently. �If I SAL DX, carry is not brought in. �If I
> > RCL DX, I lose my sign bit.
>
> Actually you don't lose the sign bit. A new bit becomes the sign bit and it
> will correct Unless the number overflows.
>
>
>
> > This is obviously a solved problem; what is the common way of doing
> > this? �I thought of masking the sign bit, grabbing it into a register,
> > then ORing it to DX when done shifting, but this seems inelegant.
>
> It doesn't even help. OR-ing the sign back onto it will have no effect in
> most cases, and when it Does the result will not make sense.
>
> Examples:
>
> 0xFFFF : 0xFFFF shifted left by 1:
> 0xFFFF : 0xFFFE = correct, no OR needed
>
> 0x8000 : 0x0000
> 0x0000 : 0x0000 overflow. but there is no way to fix that. sticking the old
> sign in front of it doesn't create a meaningful value.
>
> 0x7FFF : 0x0000
> 0xFFFE : 0x0000 signed overflow. instead of OR-ing you'd need AND-ing, but
> even that wouldn't help. 0x7FFE : 0x0000 isn't any more useful to get as an
> answer.
Do you realize that to have a left shift w/o an overflow you have to
satisfy one simple requirement???: having enough bits for the result.
Alex
|
|
0
|
|
|
|
Reply
|
Alexei
|
2/9/2009 5:41:08 PM
|
|
Jim Leonard wrote:
> I'm working on a hobby project in 16-bit DOS and trying to figure out
> how to do a signed shift left of a 32-bit signed integer in DX:AX. I
> have already figured out a signed shift right:
>
> mov cx,bits_to_shift
> shift:
> sar dx,1 ;signed shr, bit into carry
> rcr ax,1 ;rotate carry right
> loop @shift
>
> ....but I am having the damnest time figuring out how to do a signed
> shift left efficiently. If I SAL DX, carry is not brought in. If I
> RCL DX, I lose my sign bit.
>
> This is obviously a solved problem; what is the common way of doing
> this? I thought of masking the sign bit, grabbing it into a register,
> then ORing it to DX when done shifting, but this seems inelegant.
>
An unsigned shift left is the same as signed shift left!
I.e. you can do this any number of ways, with SHLD being the easiest:
SHLD DX,AX,CL
SHL AX,CL
or if you know that the CL count will be small but non-zero:
shift:
add ax,ax
adc,dx,dx
loop shift
or you can do
shift:
shl ax,1
rcl dx,1
loop shift
If you have the additional requirement that you want to keep the
original sign bit, then you're not really doing a signed shift, but a
clamped multiplication of any negative input.
I.e. any negative value that becomes larger than 32768 in magnitude
(less than -32768 in real value) should be clamped to -32768.
This kind of math can make sense, but normally only if you also clamp
positive values, probably to 32767.
The negative clamping can indeed be most easily handled with a
save/restore of the original sign bit, positive clamping is
significantly harder.
You also have to decide how to handle shift counts that would result in
total overflow, i.e. zero result bits within the 32-bit area set aside.
Terje
--
- <Terje.Mathisen at tmsw.no>
"almost all programming can be viewed as an exercise in caching"
|
|
0
|
|
|
|
Reply
|
Terje
|
2/9/2009 7:25:34 PM
|
|
"Jim Leonard" <spamtrap@crayne.org> wrote in message
news:9013cf07-2155-46ba-bcf7-1609df158dc9@f40g2000pri.googlegroups.com...
> I'm working on a hobby project in 16-bit DOS and trying to figure out
> how to do a signed shift left of a 32-bit signed integer in DX:AX. I
> have already figured out a signed shift right:
>
> mov cx,bits_to_shift
> shift:
> sar dx,1 ;signed shr, bit into carry
> rcr ax,1 ;rotate carry right
> loop @shift
>
> ...but I am having the damnest time figuring out how to do a signed
> shift left efficiently. If I SAL DX, carry is not brought in. If I
> RCL DX, I lose my sign bit.
>
> This is obviously a solved problem; what is the common way of doing
> this? I thought of masking the sign bit, grabbing it into a register,
> then ORing it to DX when done shifting, but this seems inelegant.
>
Okay, I'll take it you're trying to preserve the upper most bit, while
shifting the remaining bits left. Something like this might work:
shl ax,1
rcl dx,1
pushf
shl dx,1
popf
rcr dx,1
Rod Pemberton
|
|
0
|
|
|
|
Reply
|
Rod
|
2/9/2009 10:50:22 PM
|
|
[...]
>
> Do you realize that to have a left shift w/o an overflow you have to
> satisfy one simple requirement???: having enough bits for the result.
>
> Alex
>
I don't really see what that has to do with it, I was just writing about the
effects of overflows of negative numbers
For negative numbers a left shift always results in an unsigned overflow but
that doesn't make the result bad unless it was also a signed overflow
|
|
0
|
|
|
|
Reply
|
Harold
|
2/9/2009 11:14:28 PM
|
|
On Feb 9, 4:50�pm, "Rod Pemberton" <spamt...@crayne.org> wrote:
> "Jim Leonard" <spamt...@crayne.org> wrote in message
>
> news:9013cf07-2155-46ba-bcf7-1609df158dc9@f40g2000pri.googlegroups.com...
>
>
>
>
>
> > I'm working on a hobby project in 16-bit DOS and trying to figure out
> > how to do a signed shift left of a 32-bit signed integer in DX:AX. �I
> > have already figured out a signed shift right:
>
> > � mov cx,bits_to_shift
> > shift:
> > � sar dx,1 � � �;signed shr, bit into carry
> > � rcr ax,1 � � � ;rotate carry right
> > � loop @shift
>
> > ...but I am having the damnest time figuring out how to do a signed
> > shift left efficiently. �If I SAL DX, carry is not brought in. �If I
> > RCL DX, I lose my sign bit.
>
> > This is obviously a solved problem; what is the common way of doing
> > this? �I thought of masking the sign bit, grabbing it into a register,
> > then ORing it to DX when done shifting, but this seems inelegant.
>
> Okay, I'll take it you're trying to preserve the upper most bit, while
> shifting the remaining bits left. �Something like this might work:
>
mov bx, 0 ;; preset for this method..
> shl ax,1
;; low order word, zero shifted in.
> rcl dx,1
;; shift high order word, adding in carry from prev. shift.
;; "The carry flag is treated 'as part of' the destination
;; operand; that is, its value is rotated into the low-
;; order bit of the destination, and itself is replaced
;; by the high order bit of the destination."
The question for Jim is, what is it he wants now, whether the sign of
the 32bit shift is to be 'shifted' back into the result.
..if. yes, and we had preset bx=0 by mov bx,0 then:
adc ax,bx ;; effectively sets bit0 to CF value if bx == 0.
Steve
> pushf
> shl dx,1
> popf
> rcr dx,1
>
> Rod Pemberton- Hide quoted text -
>
> - Show quoted text -
|
|
0
|
|
|
|
Reply
|
s_dubrovich
|
2/10/2009 4:53:28 PM
|
|
I've done some more thinking about optimal sequences for multi-bit
dual-register shifts with clamping:
Negative inputs:
mov bx,dx
shld dx,ax,cl
and bx,08000h
shl ax,cl
or dx,bx
This is pretty close to optimal when only negative values needs to be
clamped (to 080000000h).
Clamping positive values (to 07fffffffh) with the same style of code is
a lot harder I think...
A possible first step is to test for and detect shifts of more than 30
bits, this should always result in a clamped value, right?
max_shift:
mov bx,dx
xor ax,ax
sar bx,15 ; -1 or 0
mov dx,8000h
; At this point DX:AX has 8000:0000, the clamped positive value
; and BX is either -1 or 0
add ax,bx ; 0000 -> 0000 or 0ffffh
add dx,bx ; 8000 -> 8000 or 07fffh
The problem is how to do the right thing for all other inputs, with
in-range shift counts that still leads to overflow trouble.
For all negative inputs we want at least the sign bit to remain, so that
part is easy, but for positive inputs we have to determine if it was
non-zero, and the shift results turned out to be smaller than the input,
in which case the maximum positive result should come out.
Some of these things are easy to do in a branchless manner, others are
much harder!
Any ideas?
Terje
--
- <Terje.Mathisen at tmsw.no>
"almost all programming can be viewed as an exercise in caching"
|
|
0
|
|
|
|
Reply
|
Terje
|
2/10/2009 7:40:22 PM
|
|
On Feb 9, 10:05�am, "Harold Aptroot" <spamt...@crayne.org> wrote:
> Examples:
>
> 0xFFFF : 0xFFFF shifted left by 1:
> 0xFFFF : 0xFFFE = correct, no OR needed
>
> 0x8000 : 0x0000
> 0x0000 : 0x0000 overflow. but there is no way to fix that. sticking the old
> sign in front of it doesn't create a meaningful value.
And it is with this very helpful batch of replies that I finally
understand how intel architecture handles signed numbers. Thanks to
everyone who replied!
While I appreciate the pontification of the always helpful Terje, I
was not attempting to clamp, or handle overflow -- I just wanted to
mul/div a 32-bit signed integer by powers of two.
For the curious, the project this is for is a Mandelbrot/Julia set
renderer for an old IBM XT. I'm trying to beat fractint's speed
without looking at their code, and my question was related to my fixed-
point routines (this is my first foray into fixed-point).
Unfortunately, I'm hitting another barrier -- a Q1.14 fixed-point
number isn't enough precision to handle any meaningful results. I'm
going to have to work on some sort of arbitrary-length fixed-point
library; maybe something like a Q3.28 number with 64-bit temporary to
handle overflow or something...
|
|
0
|
|
|
|
Reply
|
Jim
|
2/11/2009 5:55:19 AM
|
|
Terje Mathisen wrote:
> I've done some more thinking about optimal sequences for multi-bit
> dual-register shifts with clamping:
>
> Negative inputs:
>
> mov bx,dx
> shld dx,ax,cl
> and bx,08000h
> shl ax,cl
> or dx,bx
Not sure what you're getting at here... This only keeps the sign bit,
right? It doesn't clamp to 0x80000000?
> Clamping positive values (to 07fffffffh) with the same style of code is
> a lot harder I think...
>
> A possible first step is to test for and detect shifts of more than 30
> bits, this should always result in a clamped value, right?
>
> max_shift:
> mov bx,dx
> xor ax,ax
> sar bx,15 ; -1 or 0
> mov dx,8000h
>
> ; At this point DX:AX has 8000:0000, the clamped positive value
> ; and BX is either -1 or 0
>
> add ax,bx ; 0000 -> 0000 or 0ffffh
> add dx,bx ; 8000 -> 8000 or 07fffh
So the code above simply takes a number in DX:AX, and returns 7FFF:FFFF
if it is negative and 8000:0000 if it is positive... Correct me if I'm
drunk.
> The problem is how to do the right thing for all other inputs, with
> in-range shift counts that still leads to overflow trouble.
>
> For all negative inputs we want at least the sign bit to remain, so that
> part is easy, but for positive inputs we have to determine if it was
> non-zero, and the shift results turned out to be smaller than the input,
> in which case the maximum positive result should come out.
>
> Some of these things are easy to do in a branchless manner, others are
> much harder!
>
> Any ideas?
Maybe, but I want to get a clear idea of your reasoning first.
Bjarni
--
INFORMATION WANTS TO BE FREE
|
|
0
|
|
|
|
Reply
|
Bjarni
|
2/11/2009 9:14:40 AM
|
|
Bjarni Juliusson wrote:
> Terje Mathisen wrote:
>> I've done some more thinking about optimal sequences for multi-bit
>> dual-register shifts with clamping:
>>
>> Negative inputs:
>>
>> mov bx,dx
>> shld dx,ax,cl
>> and bx,08000h
>> shl ax,cl
>> or dx,bx
>
> Not sure what you're getting at here... This only keeps the sign bit,
> right? It doesn't clamp to 0x80000000?
When all other bits have been shifted out, the sign bit is restored, so
we do indeed clamp to 0x800..
>> add ax,bx ; 0000 -> 0000 or 0ffffh
>> add dx,bx ; 8000 -> 8000 or 07fffh
>
> So the code above simply takes a number in DX:AX, and returns 7FFF:FFFF
> if it is negative and 8000:0000 if it is positive... Correct me if I'm
> drunk.
Almost correct, except exactly opposite:
Neg -> 0x80000000, Pos -> 0x7fffffff
>> Any ideas?
>
> Maybe, but I want to get a clear idea of your reasoning first.
OK now?
Terje
--
- <Terje.Mathisen at tmsw.no>
"almost all programming can be viewed as an exercise in caching"
|
|
0
|
|
|
|
Reply
|
Terje
|
2/11/2009 7:40:13 PM
|
|
Terje Mathisen wrote:
> Bjarni Juliusson wrote:
>> Terje Mathisen wrote:
>>> I've done some more thinking about optimal sequences for multi-bit
>>> dual-register shifts with clamping:
>>>
>>> Negative inputs:
DX:AX is F070:F070 and cl=4, say. My comments added in the code below.
>>> mov bx,dx ; BX is F070
>>> shld dx,ax,cl ; DX is 070F
>>> and bx,08000h ; BX is 8000
>>> shl ax,cl ; AX is 0700
>>> or dx,bx ; DX is 870F
DX:AX is now 870F:0700... or what? Not clamped.
>> Not sure what you're getting at here... This only keeps the sign bit,
>> right? It doesn't clamp to 0x80000000?
>
> When all other bits have been shifted out, the sign bit is restored, so
> we do indeed clamp to 0x800..
So it clamps to 8000:0000 if the result was 0?
>>> add ax,bx ; 0000 -> 0000 or 0ffffh
>>> add dx,bx ; 8000 -> 8000 or 07fffh
>>
>> So the code above simply takes a number in DX:AX, and returns
>> 7FFF:FFFF if it is negative and 8000:0000 if it is positive... Correct
>> me if I'm drunk.
> Almost correct, except exactly opposite:
>
> Neg -> 0x80000000, Pos -> 0x7fffffff
Let's see... DX:AX is F0F0:BABA, negative.
max_shift:
mov bx,dx ; BX is F0F0
xor ax,ax ; AX is 0000
sar bx,15 ; BX is -1
mov dx,8000h ; DX is 8000
; At this point DX:AX has 8000:0000, the clamped positive value
; and BX is either -1 or 0
add ax,bx ; 0000 -> 0000 or 0ffffh
add dx,bx ; 8000 -> 8000 or 07fffh
I get 7FFF:FFFF. What am I doing wrong?
I mean, you usually know what you are doing, so I'm assuming I'm just
missing something here. :)
Bjarni
--
INFORMATION WANTS TO BE FREE
|
|
0
|
|
|
|
Reply
|
Bjarni
|
2/11/2009 9:05:18 PM
|
|
Terje Mathisen <spamtrap@crayne.org> writes:
>I've done some more thinking about optimal sequences for multi-bit
>dual-register shifts with clamping:
<Snip>
>A possible first step is to test for and detect shifts of more than 30
>bits, this should always result in a clamped value, right?
>
>max_shift:
> mov bx,dx
> xor ax,ax
> sar bx,15 ; -1 or 0
> mov dx,8000h
>
>; At this point DX:AX has 8000:0000, the clamped positive value
>; and BX is either -1 or 0
>
> add ax,bx ; 0000 -> 0000 or 0ffffh
> add dx,bx ; 8000 -> 8000 or 07fffh
Now, you would require an initial test for zero?
Steve N.
|
|
0
|
|
|
|
Reply
|
Steve
|
2/11/2009 10:36:38 PM
|
|
I responded before, but google groups ate my reply, so I'll reply
quickly again:
On Feb 9, 10:05�am, "Harold Aptroot" <spamt...@crayne.org> wrote:
> Examples:
>
> 0xFFFF : 0xFFFF shifted left by 1:
> 0xFFFF : 0xFFFE = correct, no OR needed
>
> 0x8000 : 0x0000
> 0x0000 : 0x0000 overflow. but there is no way to fix that. sticking the old
> sign in front of it doesn't create a meaningful value.
It is with this information that I finally understand how intel
hardware represents negative numbers (insert sheepish look here). So
I understand why I don't need to specially handle the sign bit now.
Thanks to all who helped.
For the curious, this is part of a larger project of mine to try to
draw a mandelbrot fractal faster than fractint can do it -- WITHOUT
looking at any fractint code. The shifting was part of my fixed-point
routines, which now function at a faster rate than my floating-point
library. (Unfortunately, I now have an overflow problem, so I'll be
trying to work up 64-bit add/sub/mul/div routines for 16-bit real
mode. If anyone has seen code like this already out there, any and
all links/advice appreciated...!)
|
|
0
|
|
|
|
Reply
|
Jim
|
2/11/2009 11:24:20 PM
|
|
Bjarni Juliusson wrote:
> Terje Mathisen wrote:
>> Bjarni Juliusson wrote:
>>> Terje Mathisen wrote:
>>>> I've done some more thinking about optimal sequences for multi-bit
>>>> dual-register shifts with clamping:
>>>>
>>>> Negative inputs:
>
> DX:AX is F070:F070 and cl=4, say. My comments added in the code below.
In the original post I wrote that this was only for when the shift count
was >30, i.e. when we know all magnitude bits will shift out.
> max_shift:
> mov bx,dx ; BX is F0F0
> xor ax,ax ; AX is 0000
> sar bx,15 ; BX is -1
> mov dx,8000h ; DX is 8000
>
> ; At this point DX:AX has 8000:0000, the clamped positive value
> ; and BX is either -1 or 0
>
> add ax,bx ; 0000 -> 0000 or 0ffffh
> add dx,bx ; 8000 -> 8000 or 07fffh
>
> I get 7FFF:FFFF. What am I doing wrong?
Ooooops! I need to invert BX after the shift and before the ADDs, or use
some other trickery...
mov bx,dx
or ax,-1
sar bx,15
mov dx,7fffh
DX:AX = 7fff:ffff, correct for positive inputs. Need to add one or
invert all bits if DX was negative, i.e. either:
add ax,bx
add dx,bx
or (probably clearer):
xor ax,bx
xor dx,bx
>
> I mean, you usually know what you are doing, so I'm assuming I'm just
> missing something here. :)
Nope, I'm simply coding while typing, with zero testing. This leads to
exactly this kind of trouble far too often. :-(
Terje
--
- <Terje.Mathisen at tmsw.no>
"almost all programming can be viewed as an exercise in caching"
|
|
0
|
|
|
|
Reply
|
Terje
|
2/12/2009 9:21:51 PM
|
|
(Steve) wrote:
> Terje Mathisen <spamtrap@crayne.org> writes:
>> I've done some more thinking about optimal sequences for multi-bit
>> dual-register shifts with clamping:
> <Snip>
>
>> A possible first step is to test for and detect shifts of more than 30
>> bits, this should always result in a clamped value, right?
>>
>> max_shift:
>> mov bx,dx
>> xor ax,ax
>> sar bx,15 ; -1 or 0
>> mov dx,8000h
>>
>> ; At this point DX:AX has 8000:0000, the clamped positive value
>> ; and BX is either -1 or 0
>>
>> add ax,bx ; 0000 -> 0000 or 0ffffh
>> add dx,bx ; 8000 -> 8000 or 07fffh
>
> Now, you would require an initial test for zero?
Yes indeed. I did realize that after posting originally, but didn't
bother to re-post about it: There are far too many oth
--
- <Terje.Mathisen at tmsw.no>
"almost all programming can be viewed as an exercise in caching"
|
|
0
|
|
|
|
Reply
|
Terje
|
2/12/2009 9:24:06 PM
|
|
(Steve) wrote:
> Terje Mathisen <spamtrap@crayne.org> writes:
>> add ax,bx ; 0000 -> 0000 or 0ffffh
>> add dx,bx ; 8000 -> 8000 or 07fffh
>
> Now, you would require an initial test for zero?
Yes, I would indeed need that.
Terje
--
- <Terje.Mathisen at tmsw.no>
"almost all programming can be viewed as an exercise in caching"
|
|
0
|
|
|
|
Reply
|
Terje
|
2/12/2009 9:24:47 PM
|
|
Jim Leonard wrote:
> For the curious, this is part of a larger project of mine to try to
> draw a mandelbrot fractal faster than fractint can do it -- WITHOUT
> looking at any fractint code. The shifting was part of my fixed-point
Heh!
I wrote some asm code back in those days, it might have been included as
one of the first properly pipelined x87 fp implementations. :-)
Anyway, Mandelbrot terminates as soon as you get >= 4, so it is easy to
use fixed-point with either direct overflow detection, or a single guard
bit.
Terje
--
- <Terje.Mathisen at tmsw.no>
"almost all programming can be viewed as an exercise in caching"
|
|
0
|
|
|
|
Reply
|
Terje
|
2/12/2009 9:27:07 PM
|
|
Jim Leonard writes:
>For the curious, this is part of a larger project of mine to try to
>draw a mandelbrot fractal faster than fractint can do it -- WITHOUT
>looking at any fractint code. The shifting was part of my fixed-point
>routines, which now function at a faster rate than my floating-point
>library. (Unfortunately, I now have an overflow problem, so I'll be
>trying to work up 64-bit add/sub/mul/div routines for 16-bit real
>mode. If anyone has seen code like this already out there, any and
>all links/advice appreciated...!)
Hi Jim,
Look/search for extended precision arithmetic. ADD/ADC and
SUB/SBB make those easy. Multiply is not bad. Keep track of
the signs and convert to unsigned/positive. Then multiply out
and add as learned in school.
[word D][word C]
X [word B][word A]
_________________
[high AC][low AC]
+ [high AD][ low AD]
+ [high BC][ low BC]
+ [High BD][ low BD]
= [four word answer that needs the sign adjusted.]
Divison is a different kettle of fish. Knuth in "Art of
Computer Programming" discusses this. I implemented a long
divide with the "test, shift, and subtract" algorithm. Not
fast, but can do a whole bunch of bits.
HTH,
Steve N.
|
|
0
|
|
|
|
Reply
|
Steve
|
2/13/2009 1:21:21 PM
|
|
Terje Mathisen <spamtrap@crayne.org> wrote in part:
> (Steve) wrote:
>> Terje Mathisen <spamtrap@crayne.org> writes:
>>> add ax,bx ; 0000 -> 0000 or 0ffffh
>>> add dx,bx ; 8000 -> 8000 or 07fffh
>>
>> Now, you would require an initial test for zero?
>
> Yes, I would indeed need that.
But very low cost since it could jmp fwd so predicted not taken.
And also early enough to skip the entire array processing.
I've been working on this, and it is reminiscent of old bit
twiddling. Perhaps dec, mask, inc, ? I can see why it is
worth some effort because saturation is not an improbable case.
-- Robert
>
|
|
0
|
|
|
|
Reply
|
Robert
|
2/13/2009 1:55:04 PM
|
|
On Feb 12, 3:27�pm, Terje Mathisen <spamt...@crayne.org> wrote:
> Anyway, Mandelbrot terminates as soon as you get >= 4, so it is easy to
> use fixed-point with either direct overflow detection, or a single guard
> bit.
Right now, that's the least of my worries; I'm using a Q1.14 format
number because anything higher and I get overflow on the multiply, but
Q1.14 is such low precision that my mandelbrot looks... odd :-) I'm
currently working on 64-bit integer routines to try to get around it.
(I am sure this problem has been solved before, but I couldn't find a
reference on basic fixed-point operations in asm for real-mode...)
|
|
0
|
|
|
|
Reply
|
Jim
|
2/13/2009 10:56:22 PM
|
|
|
21 Replies
212 Views
(page loaded in 0.262 seconds)
|