32-bit bin2ascii with 16-bit registers
Author |
Message |
Greg MacLella #1 / 8
|
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 |
|
|
Randall Hyd #2 / 8
|
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 |
|
|
Alexei A. Frounz #3 / 8
|
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 |
|
|
debs #4 / 8
|
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 |
|
|
Scott J. McCaughri #5 / 8
|
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 |
|
|
debs #6 / 8
|
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 |
|
|
Frank Kotle #7 / 8
|
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 |
|
|
TAD #8 / 8
|
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 |
|
|
|