I have to read some legacy data files used by a MS-DOS program. Most of it is quite straightforward, but I can't figure out one data type; a 6-byte sequences representing whole numbers.
Some examples:
+-----+-------------------+
| num | bytes as hex |
+-----+-------------------+
| 0 | 00 00 00 00 00 00 |
| 1 | 80 7b 14 ae 47 61 |
| 2 | 80 20 d0 91 7b 14 |
| 3 | 80 20 d0 92 5c d0 |
| 4 | 80 20 d0 92 7b 14 |
| 5 | 80 20 d0 93 5c d0 |
| 6 | 80 20 d0 93 d0 bb |
| 7 | 80 20 d0 93 7a 14 |
| 8 | 80 20 d0 93 09 e2 |
| 9 | 80 20 d0 94 d1 9b |
| 10 | 80 20 d0 94 14 d0 |
| 16 | 84 48 e1 7a 14 7e |
| 20 | 85 0a d7 a3 70 1d |
| 32 | 86 ec 51 b8 1e 20 |
| 48 | 86 86 eb 51 b8 40 |
| 73 | 87 00 00 00 00 12 |
| 100 | 87 00 00 00 00 48 |
| 130 | 88 00 00 00 80 01 |
+-----+-------------------+
Things that may be useful to know:
Any help is very welcome!
Quick Update
The example above shows a sequence of bytes, represented here as hex value, cut from the file and pasted here. I'm sure the byte sequence is meant to represent a number, since I can change the numeric value inside the MS-DOS program, save to file, and compare the results.
Reading & Writing the data
In order to read and write 48 bit real to and from binary form, you could take a look at:
PHP: Convert double to Pascal 6-byte (48 bits) real format
In computer architecture, 48-bit integers can represent 281,474,976,710,656 discrete values. This allows an unsigned binary integer range of 0 through 281,474,976,710,655 or a signed two's complement range of -140,737,488,355,328 through 140,737,488,355,327.
byte: The byte data type is an 8-bit signed two's complement integer. It has a minimum value of -128 and a maximum value of 127 (inclusive).
4-byte values (word, int) If we combine 4 bytes, we get a value with 32 bits, which can store 65536*65536 distinct values. This gives a range of approximately 4 billion different values. In many languages, a data type referred to simply as an "int" (=integer) is assumed to be 4 bytes.
This looks like 6 byte[48 bit] real float point pascal format
A Pascal real has a value between 2.9E-39 (2.9 x 10^-39) to 1.7E38 (1.7 x 10^38).
if this is the case you could convert from the hex number to double with this method.
[I took it from wiki listed bellow at article end but anyway: Turbo Pascal Real]
// This program expects a byte array named real48[6] to be loaded with the 6 bytes of the real from the file.
Double exponentbase = 129d;
Double exponent = real48[0] - exponentbase; // The exponent is offset so deduct the base.
// Now Calculate the mantissa
Double mantissa = 0.0;
Double value = 1.0;
// For Each Byte.
for (int i = 5; i >= 1; i--)
{
int startbit = 7;
if (i == 5)
{ startbit = 6; } //skip the sign bit.
//For Each Bit
for (int j = startbit; j >= 0; j--)
{
value = value / 2;// Each bit is worth half the next bit but we're going backwards.
if (((real48[i] >> j) & 1) == 1) //if this bit is set.
{
mantissa += value; // add the value.
}
}
}
if (mantissa == 1.0 && real48[0] == 0) // Test for null value
return 0.0;
if ((real48[5] & 0x80) == 1) // Sign bit check
mantissa = -mantissa;
return (1 + mantissa) * Math.Pow(2.0, exponent);
If you want a more modern | POO code to achieve that you could use the code Simeon Pilgrim show us in this article :
Pascal 6-byte real to IEEE 8-byte double
Warning To use the method exposed by Pilgrim you need to be careful with byte ordering
// expl: 100=> 87 00 00 00 00 48 var theMethodParam = new ushort[] { 0x0087, 0x0000, 0x4800 };
You can get more info about this topic here:
Turbo Pascal Real
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With