Signed shift of 32-bit int using 16-bit instructions?

  • Follow


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)

Similiar Articles:


















7/21/2012 12:07:52 AM


Reply: