* Type conversion / computing problem
@ 2000-02-17 0:00 Andreas
0 siblings, 0 replies; 4+ messages in thread
From: Andreas @ 2000-02-17 0:00 UTC (permalink / raw)
Hi!
I need advice on a nice problem with data type conversions in Ada95 with GNAT:
I am writing an small interpreter for an assembly-like language whose entire
data should be stored in memory as the amount of bytes needed for a particular
Ada-type (e.g. 4 bytes for Integers, 8 bytes for Long_Floats) and each of those
bytes should be separately addressable. A register for this assembler should be
8 bytes and the rightmost byte is the least significant one.
A register (just an array variable of type RegType) has to be an intermediate
variable that should allow converting any type A to any type B (so I don't have
to write separate functions for each possible conversion). So the functionality
should be this (e.g.):
4-byte-Integer (e.g. 5) --> Register, bytes 5-8, least significant right -->
8-byte-Integer (e.g. 5)
or
4-byte-Integer (e.g. 5) --> Register, bytes 5-8, least significant right -->
2-byte-Integer (e.g. 5)
(the --> denote conversions). Of course, the value of the integers should not
change when converted to a larger type. When converted to a Ada type, only
the amount of bytes required for this type should be considered in the Register,
thus (perhaps) changing the value (e.g. use the rightmost 2 bytes of the
register
for a Short_Integer).
Currently I am using the following code for splitting/converting the Integer
types into the array of bytes (register) and back (only functions for
Standard.Integer given, for other Integers same algorithm):
type Byte is mod 256; -- an unsigned byte
type RegType is array (1..8) of Byte; -- register
type BitIndexType is mod 8; -- for converting purposes
-- This function converts data type Integer into an array of Byte's
function RAS_Integer2Reg (IntValue: in Integer) return RegType is
TempReg: RegType:= (others => 0); -- initialize with 0
BitIndex: BitIndexType := 0;
ByteIndex: Integer := 8; -- least significant byte right in register
Remainder: Integer;
LocalIntValue: Integer;
begin
LocalIntValue := IntValue;
while LocalIntValue /= 0 loop
Remainder := LocalIntValue mod 2;
LocalIntValue := LocalIntValue / 2;
TempReg(ByteIndex) := TempReg(ByteIndex) + Byte(Remainder *
2**Integer(BitIndex));
if BitIndex = 7 then
ByteIndex := ByteIndex - 1; -- switch to next byte
end if;
BitIndex := BitIndex + 1;
end loop;
return TempReg;
end RAS_Integer2Reg;
-- This function converts the array of Byte's into an Integer value
function RAS_Reg2Integer (RegValue: in RegType) return Integer is
TempInt: Integer := 0;
BitIndex: Integer := 0; -- this time no mod type!
begin
for ByteIndex in reverse 5..8 loop -- Integer is only 4 bytes out of the
-- 8 in RegType
TempInt := TempInt + Integer(RegValue(ByteIndex)) * 2**BitIndex;
BitIndex := BitIndex + 8;
end loop;
return TempInt;
end RAS_Reg2Integer;
Now, the problem is that these functions work perfectly only for positive
Integers (I guess because of the unsigned Byte), not for negative values.
Unfortunately, I cannot change the types Byte and RegType since they are
required. How can I use the same data types for processing negative values
without defining a signed byte like "type Byte is Integer range -128..127"
(and I don't even think this would help)???
Furthermore it's required for an associated debugger that the entire register
should be displayed as an 8-byte-Integer (I use Long_Long_Integer, but have
already also tried a self-defined 64-bit-type for this). So if you do the
conversion:
4-byte-Integer (Standard.Integer) --> RegType --> 8-byte-Integer (Long_Long_Int)
the original value should of course be the same in 8-byte-Integer.
This as well, when using the algorithms above, works only for positive values.
For this example, I already tried defining a 8-Byte-array, doing an
Unchecked_Conversion and changing the byte order "manually" (of course by
program ;-)). But when I do this, Unchecked_Conversion seems to fill the byte
array from left to right, not as required, from right to left, thus changing the
original value. And the problem with negative values still persists.
I would greatly appreciate any hints on how I can solve this problem of storing
negative (Integer) values in an array of unsigned bytes with least significant
byte right.
(Yes, I'm looking for a rather uncomplicated solution, not writing a long
algorithm with distinction between positive and negative values :-), but I would
also be very happy about such a longer solution).
Thanks in advance!
Andreas
P.S. Could you please send the reply via e-mail, too?! :-)
^ permalink raw reply [flat|nested] 4+ messages in thread
* Type conversion / computing problem
@ 2000-02-17 0:00 Andreas
2000-02-17 0:00 ` Robert A Duff
0 siblings, 1 reply; 4+ messages in thread
From: Andreas @ 2000-02-17 0:00 UTC (permalink / raw)
Hi!
I need advice on a nice problem with data type conversions in Ada95 with GNAT:
I am writing an small interpreter for an assembly-like language whose entire
data should be stored in memory as the amount of bytes needed for a particular
Ada-type (e.g. 4 bytes for Integers, 8 bytes for Long_Floats) and each of those
bytes should be separately addressable. A register for this assembler should be
8 bytes and the rightmost byte is the least significant one.
A register (just an array variable of type RegType) has to be an intermediate
variable that should allow converting any type A to any type B (so I don't have
to write separate functions for each possible conversion). So the functionality
should be this (e.g.):
4-byte-Integer (e.g. 5) --> Register, bytes 5-8, least significant right -->
8-byte-Integer (e.g. 5)
or
4-byte-Integer (e.g. 5) --> Register, bytes 5-8, least significant right -->
2-byte-Integer (e.g. 5)
(the --> denote conversions). Of course, the value of the integers should not
change when converted to a larger type. When converted to a Ada type, only
the amount of bytes required for this type should be considered in the Register,
thus (perhaps) changing the value (e.g. use the rightmost 2 bytes of the
register
for a Short_Integer).
Currently I am using the following code for splitting/converting the Integer
types into the array of bytes (register) and back (only functions for
Standard.Integer given, for other Integers same algorithm):
type Byte is mod 256; -- an unsigned byte
type RegType is array (1..8) of Byte; -- register
type BitIndexType is mod 8; -- for converting purposes
-- This function converts data type Integer into an array of Byte's
function RAS_Integer2Reg (IntValue: in Integer) return RegType is
TempReg: RegType:= (others => 0); -- initialize with 0
BitIndex: BitIndexType := 0;
ByteIndex: Integer := 8; -- least significant byte right in register
Remainder: Integer;
LocalIntValue: Integer;
begin
LocalIntValue := IntValue;
while LocalIntValue /= 0 loop
Remainder := LocalIntValue mod 2;
LocalIntValue := LocalIntValue / 2;
TempReg(ByteIndex) := TempReg(ByteIndex) + Byte(Remainder *
2**Integer(BitIndex));
if BitIndex = 7 then
ByteIndex := ByteIndex - 1; -- switch to next byte
end if;
BitIndex := BitIndex + 1;
end loop;
return TempReg;
end RAS_Integer2Reg;
-- This function converts the array of Byte's into an Integer value
function RAS_Reg2Integer (RegValue: in RegType) return Integer is
TempInt: Integer := 0;
BitIndex: Integer := 0; -- this time no mod type!
begin
for ByteIndex in reverse 5..8 loop -- Integer is only 4 bytes out of the
-- 8 in RegType
TempInt := TempInt + Integer(RegValue(ByteIndex)) * 2**BitIndex;
BitIndex := BitIndex + 8;
end loop;
return TempInt;
end RAS_Reg2Integer;
Now, the problem is that these functions work perfectly only for positive
Integers (I guess because of the unsigned Byte), not for negative values.
Unfortunately, I cannot change the types Byte and RegType since they are
required. How can I use the same data types for processing negative values
without defining a signed byte like "type Byte is Integer range -128..127"
(and I don't even think this would help)???
Furthermore it's required for an associated debugger that the entire register
should be displayed as an 8-byte-Integer (I use Long_Long_Integer, but have
already also tried a self-defined 64-bit-type for this). So if you do the
conversion:
4-byte-Integer (Standard.Integer) --> RegType --> 8-byte-Integer (Long_Long_Int)
the original value should of course be the same in 8-byte-Integer.
This as well, when using the algorithms above, works only for positive values.
For this example, I already tried defining a 8-Byte-array, doing an
Unchecked_Conversion and changing the byte order "manually" (of course by
program ;-)). But when I do this, Unchecked_Conversion seems to fill the byte
array from left to right, not as required, from right to left, thus changing the
original value. And the problem with negative values still persists.
I would greatly appreciate any hints on how I can solve this problem of storing
negative (Integer) values in an array of unsigned bytes with least significant
byte right.
(Yes, I'm looking for a rather uncomplicated solution, not writing a long
algorithm with distinction between positive and negative values :-), but I would
also be very happy about such a longer solution).
Thanks in advance!
Andreas
P.S. Could you please send the reply via e-mail, too?! :-)
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: Type conversion / computing problem
2000-02-17 0:00 Andreas
@ 2000-02-17 0:00 ` Robert A Duff
2000-02-22 0:00 ` Oliver Kellogg
0 siblings, 1 reply; 4+ messages in thread
From: Robert A Duff @ 2000-02-17 0:00 UTC (permalink / raw)
Andreas <Amun_Ra72@gmx.net> writes:
> Now, the problem is that these functions work perfectly only for positive
> Integers (I guess because of the unsigned Byte), not for negative values.
You could convert each signed integer to a modular of the same size
using Unchecked_Conversion. And I think your code already knows how to
convert that to an array-of-8-bytes, with the right byte ordering.
Or, unchecked conv signed to modular of same size, then use a normal
type_conversion to convert to a "mod 2**64" type, then unchecked convert
that to array-of-8-bytes, then apply a byte-swap procedure to that
array.
- Bob
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: Type conversion / computing problem
2000-02-17 0:00 ` Robert A Duff
@ 2000-02-22 0:00 ` Oliver Kellogg
0 siblings, 0 replies; 4+ messages in thread
From: Oliver Kellogg @ 2000-02-22 0:00 UTC (permalink / raw)
Bob Duff pointed the way; here's a possible implementation
(I happen to have had a similar problem a while ago.)
with Ada.Text_IO;
with Interfaces, System, Unchecked_Conversion;
use Interfaces;
procedure RegTest is
subtype Byte is Unsigned_8;
subtype Var_Positive is Positive range 1 .. 8;
type Byte_Array is array (Var_Positive range <>) of Byte;
pragma Pack (Byte_Array);
subtype Two_Bytes is Byte_Array (1 .. 2);
subtype Four_Bytes is Byte_Array (1 .. 4);
subtype RegType is Byte_Array (1 .. 8);
function To_Bytes is new Unchecked_Conversion
(Unsigned_64, RegType);
function Maybe_Swap (Bytes : Byte_Array)
return Byte_Array is
Tmp : Byte_Array (1 .. Bytes'Length);
begin
if System."=" (System.Default_Bit_Order,
System.Low_Order_First) then
for I in Tmp'Range loop
Tmp (I) := Bytes (Bytes'Last - I + 1);
end loop;
else
Tmp := Bytes;
end if;
return Tmp;
end Maybe_Swap;
function Int2Reg (Value : Integer_32) return RegType is
function To_Unsigned is new Unchecked_Conversion
(Integer_64, Unsigned_64);
U64 : Unsigned_64;
begin
U64 := To_Unsigned (Integer_64 (Value));
return Maybe_Swap (To_Bytes (U64));
end Int2Reg;
function Reg2Int (Value : RegType) return Integer_32 is
function To_Integer is new Unchecked_Conversion
(Four_Bytes, Integer_32);
begin
return To_Integer (Maybe_Swap (Value (5 .. 8)));
-- Interestingly, we can use fixed indexes here (5..8)
-- regardless of host endianness.
-- That is because on a little endian machine not only are
-- the bytes in reverse sequence, but also the numbering of
-- bytes is reversed. ("two wrongs make one right")
end Reg2Int;
package Byte_IO is new Ada.Text_IO.Modular_IO (Byte);
RegVar : RegType;
IntVar : Integer_32;
begin
RegVar := (1 .. 7 => 0, 8 => 1); -- one
IntVar := Reg2Int (RegVar) + 1; -- two
RegVar := Int2Reg (IntVar);
for I in 1 .. 8 loop
-- output should be (0,0,0,0,0,0,0,2)
Ada.Text_IO.Put (' ');
Byte_IO.Put (RegVar (I), Base => 16);
end loop;
Ada.Text_IO.New_Line;
RegVar := (1 .. 8 => 16#FF#); -- minus one
IntVar := Reg2Int (RegVar) - 1; -- minus two
RegVar := Int2Reg (IntVar);
for I in 1 .. 8 loop
-- output should be (FF,FF,FF,FF,FF,FF,FF,FE)
Ada.Text_IO.Put (' ');
Byte_IO.Put (RegVar (I), Base => 16);
end loop;
Ada.Text_IO.New_Line;
end RegTest;
Sent via Deja.com http://www.deja.com/
Before you buy.
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2000-02-22 0:00 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2000-02-17 0:00 Type conversion / computing problem Andreas
-- strict thread matches above, loose matches on Subject: below --
2000-02-17 0:00 Andreas
2000-02-17 0:00 ` Robert A Duff
2000-02-22 0:00 ` Oliver Kellogg
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox