I am looking for help, ideas, etcetera on how to convert between two number bases.
Posted on 2003-02-26 03:40:12 by jInuQ
to convert from decimal to binary divide the number by two and write the remainder from right to left until the result is zero
ex: 11/2 = 5, rem 1
5/2 = 2, rem 1
2/2 = 1, rem 0
1/2 = 0, rem 1
the binary number is 1011b. ("b" means "binary")

to convert from binary to decimal add the powers of 2's respectively to the positions of ones from rigt to left in the binary number
ex: 1001101b = 1*2^0 + 0*2^1 + 1*2^2 + 1*2^3 + 0*2^4 + 0*2^5 + 1*2^6 = 1 + 4 + 8 + 64 = 76

you will be able to convert from hex to decimal if you undersood the convertion of binary to decimal, it is made in the same way but the base is naturally 16.

the convertion of binary to hex is even easier, you consider every four bits (digits) of binary as one respective digit of hex
ex: (1010 0110 1001)b = A69h

please ask if i can help you some more...:alright:
Posted on 2003-02-26 14:49:42 by applecin
If you want the computer to do it, the general strategy is to 1) get the number in string form, 2) convert it to a suitable numeric form, and then 3) convert it to a string form.


Conversion (of integers) to a numeric form works roughly like this:

Start with accumulator = 0.
For each digit from left to right, new accumulator = (base * accumulator) + converted-digit.

Each digit must be converted from its character value to its numeric value.


Conversion (of integers) to string form works roughly like this:

Start with accumulator = number.
Generate digits from right to left by repeatedly applying these two steps:
1) Convert (accumulator mod base) to character value.
2) New accumulator = accumulator / base.
Stop when accumulator is 0.
Posted on 2003-02-26 15:41:58 by tenkey
Sorry I should have been more clear. What I was looking for was not so much the method to convert numbers but an idea on how to implement it in assembly. I had done some work useing a method like applecin said. I was told to use shifts instead , but could quite get what they were talking about.
Posted on 2003-02-26 16:18:10 by jInuQ
I'm also trying something like base conversion for decimal to hexadecimal, and its rather easy (at least i think)

mov ax,75 ;73 is the number to divide by 16
mov bh,16 ;base 16
div bh

Opcodes.hlp says for div:

DIV - Divide
Usage: DIV src
Modifies flags: (AF,CF,OF,PF,SF,ZF undefined)
Unsigned binary division of accumulator by source. If the source
divisor is a byte value then AX is divided by "src" and the quotient
is placed in AL and the remainder in AH. If source operand is a word
value, then DX:AX is divided by "src" and the quotient is stored in AX
and the remainder in DX.

Read the values from AL and AH (this goes for any conversion using division) and go from there, at least this is how im going about implementing decimal to hexadecimal.

EDIT: By the way, this might help you a lot:

Posted on 2003-02-26 16:36:16 by kairon

Sorry I should have been more clear. What I was looking for was not so much the method to convert numbers but an idea on how to implement it in assembly. I had done some work useing a method like applecin said. I was told to use shifts instead , but could quite get what they were talking about.

i think whoever said you should use shifts was assuming you knew the base before hand and could replace the slow "div" instruction with a few shifts. not used to doing division in assembly, so perhaps someone could help you in optimizing that.

anyhoo, for base conversions, we use the principle that any positive (integer) number can be expressed in the form of (a0)b^n+(a1)b^(n-1)+(a2)b^(n-2)+...+(an)b^0

where the number after 'a' is the index and the value of each element is an integer <b.
for example, in base ten, b is 10. the number 53 is:

in base 2 (i.e. binary), pick a value for n which, when two is raised to its power, is greater than 53. e.g., log(53)/log(2)=~5.7. Round down because rounding up results in a number larger than the number to be converted, which means that the co-efficient of anything larger than 5, for a(x)=0 (i.e., you'd end up with a number like 000053).

So, we take this value of n, 5 in the example above, and raise 2 to the power of 5. Recurse down for co-efficients (sorry - that's unclear so i'll give an example):
So we start from the first element and work to the right.

a0*2^5=53... what is the largest value of a0? that is, what is the largest value for a0 such that (a0)*2^5<=53? a0=floor(53/32)=1.
so, assembly, that would translate to
mov ax,53
mov bh,32
div bh
The remainder, which is what we are now working with, is 21 - in ah. The integer portion is in al, which has the value 1. So, the first digit is one.

Next value of n. n=4
a1=1 R=5

a2=0 R=5

a3=1 R=1

a4=0 R=1

a5=1 R=0

therefore, the number 53, in binary, is 110101.

The algo, in pseudo code is thus (since i can't test it):
mov cx,n
mov ax,number
;do some exponential stuff here to get base^cx. probably easier to use FPU to multiply by the inverse of the base... anyway
mov bh,base^cx
div bh
;save al somewhere: it is the next digit
dec cx
shr ax,8 (get rid of al; put ah in its place)
jnz @B

btw, converting to binary is much easier: you can keep shifting the number left and keep testing the high bit for a "1"
Posted on 2003-02-26 18:10:31 by jademtech
I guess it would also be quite helpful if I provide some more info. The biggest thing I am tring to do is convert from base 16,10,8,2 to base 3. More spicificly balanced ternary http://perun.hscs.wmin.ac.uk/~jra/ternary/. I think this should help.

Thanks for the code jademtech.
Posted on 2003-02-26 18:56:11 by jInuQ
Here is some quick code to convert from a base that is a power of two into a dword (it uses MMX) - also untested due to lack of a computer that has MMX capabilities, not to mention an assembler, other than debug, if it can be called that :( :

mov bleh,0
mov ebx,-n ;where 2^n=base that you are converting from. so, the negative value of n...
lea eax,strNum ;load a pointer in eax to the number to be converted
mov ecx,lenStr ;move the pointer to the end of the string using a zero-based offset (i.e. a 1-character number is 0, 2-characters is 1, etc.)
mov edx,[eax+ecx] ;get value at eax
add ebx,n ;where 2^n=base that you are converting from
and edx,0fh ;keeps only last four bits. hope i got my endians straight. this is to avoid prefixing eax /w a byte code above. assumes you've converted ascii characters 0-9 and a-f.
shl edx,ebx ;edx*[(2^n)^(iteration-1)]
add bleh,edx
dec ecx

that should do the trick... my bad. didn't end up using MMX instructions :) reading up on balanced ternary.
Posted on 2003-02-26 21:16:55 by jademtech
here's some algo for division by 3 - I can't assure it's accuracy, I also never tested it thoroughly...
mov     eax, num

mov ecx, eax

shr eax, 2
add eax, ecx
shr eax, 1
mov ecx, eax
shr eax, 4
add eax, ecx
mov ecx, eax
shr eax, 8
add eax, ecx
shr eax, 1
make use of a loop here and the stack.

do these steps
    [*]multiply eax by 3, this is shr by 1 and add the original value of eax (eax = eax >> 1 + eax) or (eax = eax * 2 + eax)
    [*]subtract the number and eax (x = num - eax)
    [*]This will be your remainder or simply your LSD of the final answer. HINT: push into the stack, make use of a counter to track the number of items pushed and pop it afterwards (decrementing the counter) then convert it to ascii (ascii character = popped value +30h), and finally place into buffer

    Posted on 2003-02-27 01:46:14 by arkane