The IEEE754 standard says:

1 bit sign

8 bit exponent

23 bit mantissa

Microchip variation:

8 bit exponent

1 bit sign

23 bit mantissa

so a number like -4.4 in Microchip hexadecimal representation would look like:

**81 8C CC CD**

Which in binary would be:

**10000001 10001100 11001100 11001101**

Now if you are not extremely familiar with how to convert floating point numbers to binary and back, you might like to use this tool from Harald Schmidt which will do it for you.

According to the standard -4.4 in binary is

**11000000 10001100 11001100 11001101**

and in Hex:

**C0 8C CC CD**

The first thing to notice (quite obviously really) is that the last two bytes are the same in both representations

**CC CD**hence we don't need to touch them, great! Now let's see what we would need to do in order to "adjust" the other two bytes to match the IEEE754 standard.

The green digit needs to "fly" in front of the blues which in turn need to move down the bench and the reds do not move at all! This is it.

Now let's see how could this be done in Mikro C code.

Assume we have declared

float number = -4.4;

we would need to be able to access each of the four bytes representing the number so to be able to manipulate them. There are essentially two ways I can think of:

Use the built in routines Lo, Hi, Higher, Highest or use a pointer "creatively".

I like the second better.

For

**option 1**you need to remember to
#include "built_in.h"

then declare four byte-size variables

unsigned char one, two, three, four;

after which you can distribute the 4 bytes of floating point number. Three and four will not be needed for this example but it might be handy to have them for example depending on how we intend to get the floating number to the PC (e.g over a serial line).

one =Lo(number); 0x81 0b

**10000001**
two = Hi(number); 0x8C 0b

**10001100**
three = Higher(number); 0xCC 0b

**11001100**
four = Highest(number); 0xCD 0b

**11001101****Option 2**instead needs a pointer like

unsigned char *numberPoint = &number;

Now the compiler will warn "Suspicious pointer conversion", but doing so will allow us to "scan" the floating point bytes as in

one = *(numberPoint + 3); 0x81 0b

**10000001**
two = *(numberPoint + 2); 0x8C 0b

**10001100**
three = *(numberPoint + 1); 0xCC 0b

**11001100**
four = *numberPoint; 0xCD 0b

**11001101**looking at the RAM window above, if we had defined the pointer as float *(numberPoint + 1) it would have returned the value BC at location 0x49. That is because 1 in this case is 1 size of floating point numbers, in fact 4 bytes! By declaring our pointer of a type char, which is stored in one byte, we gain the necessary granularity we need to move one byte at a time in the floating point binary representation.

All right, we haven't finished yet but we are nearly there. Now we need to do our flying and shifting of bits.

A really useful thing that you can do in C is that it can embed Assembler code in your program.

Now, whatever the CPU architecture. you will always have Assembler instructions for shifting, rotating or both shifting and rotating. They are very similar commands and essentially they tell the CPU to "move" all the bits to the right or to the left. What happens to the leftmost bit when rotating to the left? It "moves" to a particular location called the carry flag (CF), if you then rotate to the right the carry flag gets back on the leftmost bit of the byte. This is what we need to know. If you really really want to know more, there is just about a ton of stuff on the Internet, just Google it.

So coming back to our bytes, we would need to rotate to the left (rlf) byte two, push the CF bit back into byte one by rotating to the right (rrf) and finally rrf the new CF to byte two. That's it!

rlf two

**10001100**CF=**1**two=**0001100x**(the x because it does not matter what was in the CF)
rrf one

**10000001**CF=**1**one=**1****1000000**
rrf two

**0001100x**CF=**x**two=**1****0001100**this is how you write it in Assembler in your Mikro C editor

asm {

bsf STATUS, C

rlf _two, 1

rrf _one, 1

rrf _two, 1

}

so now we have our

**11000000 10001100 11001100 11001101**hurrah!

I hope you found this useful, it turns out I did not need to do this for the project I was working on and that generally there are better ways to get values that are represented with floating point numbers to a PC but maybe this is for another post.

## No comments:

Post a Comment