32-bit bin2ascii with 16-bit registers 
Author Message
 32-bit bin2ascii with 16-bit registers

Hi

I'm really stuck here.. I'm trying to write a bin2ascii subroutine in x86
(16-bit registers) that will convert a 32-bit integer (ie up to 0FFFFFFFFh).
I was thinking I could just divide by 10 each time, but I'll lose the data
everytime - ie, if I do DIV word ptr[10]  (bascially) then I'll lose the DX
part of DX:AX (which stores the 32-bit number).. so after the first digit,
my results would be totally inaccurate.

My next thought was to go the other way, and divide by 1,000,000,000
(biggest 32-bit int is 4-billion something), but how do I get that value in
somewhere and divide by it?

Is there a better method (besides dividing by multiples of 10) to converting
that would work better in this situation?

Thanks



Thu, 06 May 2004 02:31:15 GMT  
 32-bit bin2ascii with 16-bit registers
You need to do an extended precision division by ten.
This is actually quite easy and the algorithm appears
in the extended precision arithmetic chapters of
"The Art of Assembly Language" at
http://webster.cs.ucr.edu (both 16 and 32-bit editions
describe the algorithm you want to use).
I realize this is probably a homework assignment, but
even so you should tell your instructor that almost every
x86 CPU in production today does 32-bit arithmetic.
Hence, s/he should allow the use of 32-bit arithmetic
and if the point is to teach extended precision operations,
the instructor should be using 64-bit arithmetic.
Randy Hyde


Quote:
> Hi

> I'm really stuck here.. I'm trying to write a bin2ascii subroutine in x86
> (16-bit registers) that will convert a 32-bit integer (ie up to 0FFFFFFFFh).
> I was thinking I could just divide by 10 each time, but I'll lose the data
> everytime - ie, if I do DIV word ptr[10]  (bascially) then I'll lose the DX
> part of DX:AX (which stores the 32-bit number).. so after the first digit,
> my results would be totally inaccurate.

> My next thought was to go the other way, and divide by 1,000,000,000
> (biggest 32-bit int is 4-billion something), but how do I get that value in
> somewhere and divide by it?

> Is there a better method (besides dividing by multiples of 10) to converting
> that would work better in this situation?

> Thanks



Thu, 06 May 2004 03:55:57 GMT  
 32-bit bin2ascii with 16-bit registers

Quote:
> Hi

> I'm really stuck here.. I'm trying to write a bin2ascii subroutine in x86
> (16-bit registers) that will convert a 32-bit integer (ie up to
0FFFFFFFFh).
> I was thinking I could just divide by 10 each time, but I'll lose the data
> everytime - ie, if I do DIV word ptr[10]  (bascially) then I'll lose the
DX
> part of DX:AX (which stores the 32-bit number).. so after the first digit,
> my results would be totally inaccurate.

> My next thought was to go the other way, and divide by 1,000,000,000
> (biggest 32-bit int is 4-billion something), but how do I get that value
in
> somewhere and divide by it?

> Is there a better method (besides dividing by multiples of 10) to
converting
> that would work better in this situation?

yes, there are 2.

1. subtracting powers of 10 (sub 10^9 until the result is negative, add 10^9
back, from the number of the subtracions you get the most significant digit.
Then, subtract 10^8 from the result the same way and continue down to 10 and
1). this is basically the division by 10 by using the good old sub(c)
instruction.

2. using the DAA instruction.
you may multiply a packed BCD number by 2 by adding it to itself. here, the
addition of each byte of the multibyte number must be followed by the DAA
instruction to correct the BCD digits and the carry flag (see more on packed
BCD and DAA in intel docs or other places).

now, put 0 to some BCD variable x (x should be 5 bytes long).
repeat the following 32 times (e.g. for 32-bit integers):
{
double x (as described above by using DAA);
add most significant bit of the number, you're converting, to x (simply set
the least significant bit of x if the most significant bit of the nuber
being converted is 1);
shift the number, you're converting, one bit left;

Quote:
}

x will contain packed BCD result.

Good Luck
--
Alexei A. Frounze
http://alexfru.chat.ru
http://alexfru.narod.ru
http://welcome.to/pmode/



Thu, 06 May 2004 05:06:41 GMT  
 32-bit bin2ascii with 16-bit registers
Hello {*filter*}folk!

On Sat, 17 Nov 2001 18:31:15 +0000 (UTC), Greg MacLellan spake thus:

Quote:
>Hi

>I'm really stuck here.. I'm trying to write a bin2ascii subroutine in x86
>(16-bit registers) that will convert a 32-bit integer (ie up to 0FFFFFFFFh).
>I was thinking I could just divide by 10 each time, but I'll lose the data
>everytime - ie, if I do DIV word ptr[10]  (bascially) then I'll lose the DX
>part of DX:AX (which stores the 32-bit number).. so after the first digit,
>my results would be totally inaccurate.

This is realtively easy. You can use operand size overrides, so that
you can operate on 32 bit numbers from 16 bit code.
Quote:

>My next thought was to go the other way, and divide by 1,000,000,000
>(biggest 32-bit int is 4-billion something), but how do I get that value in
>somewhere and divide by it?

>Is there a better method (besides dividing by multiples of 10) to converting
>that would work better in this situation?

Assuming that you have the number in EAX, you could:

        xor     edx,edx
        mov     ebx,100000      ; divide by 10^5
        div     ebx             ; now eax = X DIV 100000
                                ;     edx = X MOD 100000
        push    edx

now you can operate on the number in eax to get the high 5 digits,
then on the number that you had pushed.

Alternatively, you could add an extra loop but speed it up (not
advisable if this is school work, coz if you need to ask the teacher
proably knows you don't know enough to work this out).:

        xor     edx,edx         ; edx:eax = 32 bit number
        mov     ebx,100
        xor     ebx,ebx         ; divide by 100
        xchg    ebx,edx         ; save low 2 digits

        mov     ecx,10000
        div     ecx             ; edx = next lowest 4 digits

        xor     ecx,ecx

        aam     100             ; ah = top 2 digits
                                ; al = next 2
        xchg    ch,al
        xchg    ah,al
        aam
        add     ax,'00'         ; push first two digits
        push    ax
        mov     al,ch
        aam
        add     ax,'00'         ; push next 2 digits
        push    ax
        mov     al,dh
        aam     100
        xchg    cl,al
        xchg    al,ah
        aam
        add     ax,'00'
        push    ax
        mov     al,cl
        aam
        add     ax,'00'
        push    ax
        mov     ax,bx
        aam
        add     ax,'00'
        push    ax

This code is by no means optimised. You could tidy it up to make it
smaller by using loops, and you could probably speed it up by changing
instruction pairings and stuff (although almost every instruction in
it uses AL along with other instructions, so it might not be
straightforward).

debs

If you can smile when things go wrong, you have someone in mind to blame.



Thu, 06 May 2004 05:06:41 GMT  
 32-bit bin2ascii with 16-bit registers
: Hello {*filter*}folk!

: On Sat, 17 Nov 2001 18:31:15 +0000 (UTC), Greg MacLellan spake thus:

:>Hi
:>
:>I'm really stuck here.. I'm trying to write a bin2ascii subroutine in x86
:>(16-bit registers) that will convert a 32-bit integer (ie up to 0FFFFFFFFh).
:>I was thinking I could just divide by 10 each time, but I'll lose the data
:>everytime - ie, if I do DIV word ptr[10]  (bascially) then I'll lose the DX
:>part of DX:AX (which stores the 32-bit number).. so after the first digit,
:>my results would be totally inaccurate.

: This is realtively easy. You can use operand size overrides, so that
: you can operate on 32 bit numbers from 16 bit code.
:>
:>My next thought was to go the other way, and divide by 1,000,000,000
:>(biggest 32-bit int is 4-billion something), but how do I get that value in
:>somewhere and divide by it?
:>
:>Is there a better method (besides dividing by multiples of 10) to converting
:>that would work better in this situation?
:>
: Assuming that you have the number in EAX, you could:

:       xor     edx,edx
:       mov     ebx,100000      ; divide by 10^5
:       div     ebx             ; now eax = X DIV 100000
:                               ;     edx = X MOD 100000
:       push    edx

: now you can operate on the number in eax to get the high 5 digits,
: then on the number that you had pushed.

 But this uses 32-bit registers, when th OP indicated 16-bit. Otherwise,
 you could also use FIDIV (also, FIDIVR) on the math co-processor.



Thu, 06 May 2004 07:55:57 GMT  
 32-bit bin2ascii with 16-bit registers
Hello {*filter*}folk!

On Sat, 17 Nov 2001 23:55:57 +0000 (UTC), Scott J. McCaughrin spake
thus:

Quote:
> But this uses 32-bit registers, when th OP indicated 16-bit. Otherwise,
> you could also use FIDIV (also, FIDIVR) on the math co-processor.

I was aware of that, but thought it worth offering the option that, if
the processor the code is being written for has 32 bit registers, they
can also be used from 16 bit code. It is possible that the OP didn't
realise that the code could use 32 bit registers in the appropriate
systems.

I figured it better to offer an option that might not help than to say
nothing when it is possible that what I had to say might be useful.

debs

If you can smile when things go wrong, you have someone in mind to blame.



Thu, 06 May 2004 12:55:57 GMT  
 32-bit bin2ascii with 16-bit registers

Quote:

> Hi

> I'm really stuck here.. I'm trying to write a bin2ascii subroutine in x86
> (16-bit registers) that will convert a 32-bit integer (ie up to 0FFFFFFFFh).

Frequently asked question! But judging from the number of replies it
always gets, we apparently don't mind :) And as the replies indicate,
there's more than one way to skin a cat.

Quote:
> I was thinking I could just divide by 10 each time, but I'll lose the data
> everytime - ie, if I do DIV word ptr[10]  (bascially) then I'll lose the DX
> part of DX:AX (which stores the 32-bit number).. so after the first digit,
> my results would be totally inaccurate.

Worse than that, actually - if dx > 10, the result won't fit in ax. This
causes an error (sometimes confusingly reported as "divide by zero").
The answer is obviously to save dx somewhere. Actually, you want to do
the "high word" first (probably), so save ax somewhere, move dx into ax,
and divide that by ten until done, then get the old "low word" back and
do the same with it.

You might want to set AoA (<http://webster.cs.ucr.edu>) as your home
page for the duration...

Best,
Frank



Thu, 06 May 2004 14:55:51 GMT  
 32-bit bin2ascii with 16-bit registers
Hi all,
    here is some working code...
    compile as a tiny .COM program or simply cut n paste
    the code u need.

NOTE:
    AX = hi word,    DX = lo word

regards
    TAD

; print 32-bit number(ax.dx) as 10-digit decimal by TAD
;
   .model tiny
   .code
   org 256
go:
   mov   ax, 07FFFh  ; hi-word
   mov   dx, 0FFFFh  ; lo-word

   ;; ax.dx = 32-bit number

prtdec:
   mov   si, 10      ; divisor
   mov   bx, 10      ; loop count
div10:
   push  dx
   sub   dx, dx
   div   si
   mov   cx, ax      ; new hi-word
   pop   ax
   div   si
   xchg  ax, dx      ; dx = new lo-word
   or    al, '0'
   mov   [bx+buffer-1], al
   mov   ax, cx      ; ax = new hi-word
   dec   bx
   jnz   div10
   ret

buffer   db 10 dup (?)

   end   go



Sat, 08 May 2004 03:56:06 GMT  
 
 [ 8 post ] 

 Relevant Pages 

1. 32-bit bin2ascii with 16-bit registers

2. Division 32-Bit/32-Bit with 16-Bit Register

3. Errors: cannot use 16-bit register with a 32-bit address

4. 16, 16/32, 32 bit Forths: Pros/Cons?

5. 16 and 32 bit Addressing Using BP and EBP Registers

6. 32 bit ST communicating with 16 bit VB

7. How to use SE at any color resolution (256, 16-bit, 32-bit)

8. Can I use 16 bit DLL and 32-bit exe together

9. Changing from 16-bit to 32-bit makes zillion duplicate symbols

10. 16-bit to 32-bit woes

11. Should I use 16 bit or 32 bit??

12. Graphics Error 16-bit vs 32-bit

 

 
Powered by phpBB® Forum Software