i need to convert 8bit BIN to BCD.

I need a small and fast way of convertioning in ASM.

I am stuck!, please help ASAP.

I need to finish a project by wednesday

Carlos P

I need a small and fast way of convertioning in ASM.

I am stuck!, please help ASAP.

I need to finish a project by wednesday

Carlos P

Experts Exchange Solution brought to you by

Enjoy your complimentary solution view.

Get every solution instantly with premium.
Start your 7-day free trial.

I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

I am programming in MPLAB for the Microchip's 16f877a. I am kind of limited in the set of intruction.

Please help me out

Carlos

I've never even heard of the 16f877a until today. Do you have access to a C compiler? (Many C compilers will generate assembly language programs if you ask.)

Sorry, i've probably missed guide you. I am programing on a electronic microproccesor from microchip.

(we will use the binary value 237 as an example)

1. Assume that we have the binary value stored in variable x (x can take values from 0 to 255)

2. Let y=(x/10)*10

Since x=237, therefore y=230

3. Let n=x-y

Now n=7

4. Let y=(x/100)*10

Since x=237, therefore y=20

5. Let o=(x/10)-y

Now o=23-20=3

Shift o 4 bits to the left, and add the result to n. Now n=37 (in hexadecimal representation)

6. Let m=x/100

Since x=237, therefore m=2

7. Now m contains 02, and n contains 37 (hex.), which is the BCD representation of 237

The above algorithm uses the following instructions: DIV (division), MUL (multiplication), SUB (subtraction), ADD (addition), and SHL (shift left).

Note that DIV and MUL instructions can be implemented using loops (if not supported).

_______________

Nayer Naguib

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Programming

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Experts Exchange Solution brought to you by

Enjoy your complimentary solution view.

Get every solution instantly with premium.
Start your 7-day free trial.

This version assumes a 32 bit number. If you need fewer bits, you can reduce the maximum digit supported.

Because you want fast, the easiest thing is to unroll all the digit processing. This removes any need for an integer divide, the slowest assembly instruction.

I used a set_digit() macro from C to simplify understanding. Every assembler I've ever programmed has had a macro language more powerful than the C preprocessor, so this shouldn't present much of a challenge.

If you don't know how to do a 'while' statement in assembly, it usually looks like this:

# while (test) { stuff }

# jumpto TEST

# LOOP:

# stuff

# TEST:

# test the condition

# branch-if-true, LOOP

There are two flavors of BCD in common use. The most basic BCD encoding simply takes the value (0-9) of two decimal digits and puts them into the high- and low- nibbles of a byte, respectively:

19 -> 1,9 -> byte[1 9] -> byte[0001 1001]

That's "1 << 4" in C, and uses what are called "bit shifting" operators. For your processor it may be called "left shift" or "shift left".

To join the two nibbles, high and low, you treat them as bytes with 4 interesting bits set. To start with:

0000HHHH - high nibble value (0000 0001 = 0x01)

0000LLLL - low nibble value (0000 1001 = 0x09)

Then you move (shift left) the high nibble to the left:

1 << 4

HHHH0000 = 0001 0000 = 0x10

Then you "bitwise or" or "logical or" the two values together

0x10 | 0x09

HHHH0000

0000LLLL

HHHHLLLL -> 0x19

That is the simple BCD form. Various processors, including the 8080, 6502, and 68000 families, had special purpose instructions for dealing with data in this form, so if you intend to do complex math with the data this is where you need to be.

But transferring BCD in this form is a chore, because the byte values frequently include 0x00 and sending 0x00 across the internet (or just to a C language routine) is dangerous.

So rather than expand the BCD out to ascii bytes (simple, but wasteful of space) there is an "advanced form" of BCD that avoids nul bytes and low-order ascii characters (but does require 8-bit safe transmission). That form takes the BCD and does a binary NOT operation (most CPUs have this as a single opcode).

The encoded digit values 9 and 0 are the extreme cases for BCD. Look at their representation:

99 = 1001 1001

90 = 1001 0000

09 = 0000 1001

00 = 0000 0000

The problems here are with 00, which is a NUL when expressed as ASCII, and 09 (TAB).

By inverting the bits, we get:

99 = 0110 0110

90 = 0110 0000

09 = 1111 0110

00 = 1111 1111

The lowest possible ASCII byte is 0110 0000 = 0x60, the back-tick (`). This avoids the NULs and other control-sequence bytes, but does require that transmission support high-bit (aka 8-bit) characters. I

If you want just simple encoding, return at the end of the simple encoding section. If you also want the advanced encoding, continue through to the end.

long accum;

char buffer[10];

buf_x = 0;

#define set_digit(DIGIT) \

while (accum >= DIGIT) \

++buffer[buf_x]; \

++buf_x;

long_to_b10_digits:

set_digit( 1000000000 );

set_digit( 100000000 );

set_digit( 10000000 );

set_digit( 1000000 );

set_digit( 100000 );

set_digit( 10000 );

set_digit( 1000 );

set_digit( 100 );

set_digit( 10 );

buffer[buf_x] = accum; // 1s digit

simple_bcd_encoding:

char digits[6];

int digit_x;

/* This approach does not use digits[6], but see below. */

buf_x = 0;

for (digit_x = 0; digit_x < 5; ++digit_x) {

digits[digit_x] = (buffer[buf_x] << 4) | buffer[buf_x + 1];

buf_x += 2;

advanced_bcd_encoding:

for (digit_x = 0; digit_x < 5; ++digit_x)

digits[digit_x] = ~digits[digit_x];

digits[5] = 0;