Ada - 如何显式打包位域记录类型?
Ada - how to explicitly pack a bit-field record type?
请考虑以下实验性 Ada 程序,该程序尝试创建具有明确定义的位字段的 32 位记录,创建一个并将其输出到文件流...
with System;
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Streams.Stream_Io; use Ada.Streams.Stream_Io;
procedure Main is
type Bit is mod (2 ** 1);
type Opcode_Number is mod (2 ** 4);
type Condition_Number is mod (2 ** 4);
type Operand is mod (2 ** 9);
type RAM_Register is
record
Opcode : Opcode_Number;
Z : Bit;
C : Bit;
R : Bit;
I : Bit;
Cond : Condition_Number;
Rsvd_1 : Bit;
Rsvd_2 : Bit;
Dest : Operand;
Src : Operand;
end record;
for RAM_Register use
record
Opcode at 0 range 28 .. 31;
Z at 0 range 27 .. 27;
C at 0 range 26 .. 26;
R at 0 range 25 .. 25;
I at 0 range 24 .. 24;
Cond at 0 range 20 .. 23;
Rsvd_1 at 0 range 19 .. 19;
Rsvd_2 at 0 range 18 .. 18;
Dest at 0 range 9 .. 17;
Src at 0 range 0 .. 8;
end record;
for RAM_Register'Size use 32;
for RAM_Register'Bit_Order use System.High_Order_First;
-- ADA 2012 language reference 'full_type_declaration'
-- (page 758, margin number 8/3) for RAM_Register
pragma Atomic (RAM_Register);
-- 3 2 1 0
-- 10987654321098765432109876543210
-- OOOOzcriCONDrrDDDDDDDDDsssssssss
X : RAM_Register := (2#1000#,
2#1#,
2#1#,
2#1#,
2#1#,
2#1000#,
2#1#,
2#1#,
2#100000001#,
2#100000001#);
The_File : Ada.Streams.Stream_IO.File_Type;
The_Stream : Ada.Streams.Stream_IO.Stream_Access;
begin
begin
Open (The_File, Out_File, "test.dat");
exception
when others =>
Create (The_File, Out_File, "test.dat");
end;
The_Stream := Stream (The_File);
RAM_Register'Write (The_Stream, X);
Close (The_File);
end Main;
我使用这里的信息:https://rosettacode.org/wiki/Object_serialization#Ada and here: https://en.wikibooks.org/wiki/Ada_Programming/Attributes/%27Bit_Order(最后一个例子)来创建上面的内容。
运行 代码并使用 xxd -g1 test.dat
检查输出给出以下 12 个字节的输出...
00000000: 08 01 01 01 01 08 01 01 01 01 01 01 ............
问题:
如何将这个 32 位记录作为 32 位写入流或从中读取,观察所有位域位置?想象一下,我正在通过 RS-232 端口与微控制器通信,每个位都需要在正确的时间准确地位于正确的位置。语法 for RAM_Register use record...
似乎对 'Write
如何安排其输出没有影响。
如果我确实提供了自己的 'Read
和 'Write
实现,那么 直接 是否与 'for RAM_Register 使用记录相矛盾...`代码?
您可能必须将实例转换为无符号整数(通过未经检查的转换),然后将无符号整数写入流。 Write
的默认实现忽略了表示子句(另见 RM 13 9/3):
For composite types, the Write or Read attribute for each component is called in canonical order, [...]
所以,添加
with Interfaces; use Interfaces;
with Ada.Unchecked_Conversion;
并将RAM_Register
定义为
type RAM_Register is
record
Opcode : Opcode_Number;
Z : Bit;
C : Bit;
R : Bit;
I : Bit;
Cond : Condition_Number;
Rsvd_1 : Bit;
Rsvd_2 : Bit;
Dest : Operand;
Src : Operand;
end record with Atomic;
procedure Write
(Stream : not null access Ada.Streams.Root_Stream_Type'Class;
Item : RAM_Register);
for RAM_Register'Write use Write;
for RAM_Register use
record
Opcode at 0 range 28 .. 31;
Z at 0 range 27 .. 27;
C at 0 range 26 .. 26;
R at 0 range 25 .. 25;
I at 0 range 24 .. 24;
Cond at 0 range 20 .. 23;
Rsvd_1 at 0 range 19 .. 19;
Rsvd_2 at 0 range 18 .. 18;
Dest at 0 range 9 .. 17;
Src at 0 range 0 .. 8;
end record;
for RAM_Register'Size use 32;
for RAM_Register'Bit_Order use System.High_Order_First;
-----------
-- Write --
-----------
procedure Write
(Stream : not null access Ada.Streams.Root_Stream_Type'Class;
Item : RAM_Register)
is
function To_Unsigned_32 is
new Ada.Unchecked_Conversion (RAM_Register, Unsigned_32);
U32 : Unsigned_32 := To_Unsigned_32 (Item);
begin
Unsigned_32'Write (Stream, U32);
end Write;
这会产生
$ xxd -g1 test.dat
00000000: 01 03 8e 8f ....
注意:位序可能已经颠倒了,因为我不得不评论方面规范for RAM_Register'Bit_Order use System.High_Order_First;
请考虑以下实验性 Ada 程序,该程序尝试创建具有明确定义的位字段的 32 位记录,创建一个并将其输出到文件流...
with System;
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Streams.Stream_Io; use Ada.Streams.Stream_Io;
procedure Main is
type Bit is mod (2 ** 1);
type Opcode_Number is mod (2 ** 4);
type Condition_Number is mod (2 ** 4);
type Operand is mod (2 ** 9);
type RAM_Register is
record
Opcode : Opcode_Number;
Z : Bit;
C : Bit;
R : Bit;
I : Bit;
Cond : Condition_Number;
Rsvd_1 : Bit;
Rsvd_2 : Bit;
Dest : Operand;
Src : Operand;
end record;
for RAM_Register use
record
Opcode at 0 range 28 .. 31;
Z at 0 range 27 .. 27;
C at 0 range 26 .. 26;
R at 0 range 25 .. 25;
I at 0 range 24 .. 24;
Cond at 0 range 20 .. 23;
Rsvd_1 at 0 range 19 .. 19;
Rsvd_2 at 0 range 18 .. 18;
Dest at 0 range 9 .. 17;
Src at 0 range 0 .. 8;
end record;
for RAM_Register'Size use 32;
for RAM_Register'Bit_Order use System.High_Order_First;
-- ADA 2012 language reference 'full_type_declaration'
-- (page 758, margin number 8/3) for RAM_Register
pragma Atomic (RAM_Register);
-- 3 2 1 0
-- 10987654321098765432109876543210
-- OOOOzcriCONDrrDDDDDDDDDsssssssss
X : RAM_Register := (2#1000#,
2#1#,
2#1#,
2#1#,
2#1#,
2#1000#,
2#1#,
2#1#,
2#100000001#,
2#100000001#);
The_File : Ada.Streams.Stream_IO.File_Type;
The_Stream : Ada.Streams.Stream_IO.Stream_Access;
begin
begin
Open (The_File, Out_File, "test.dat");
exception
when others =>
Create (The_File, Out_File, "test.dat");
end;
The_Stream := Stream (The_File);
RAM_Register'Write (The_Stream, X);
Close (The_File);
end Main;
我使用这里的信息:https://rosettacode.org/wiki/Object_serialization#Ada and here: https://en.wikibooks.org/wiki/Ada_Programming/Attributes/%27Bit_Order(最后一个例子)来创建上面的内容。
运行 代码并使用 xxd -g1 test.dat
检查输出给出以下 12 个字节的输出...
00000000: 08 01 01 01 01 08 01 01 01 01 01 01 ............
问题:
如何将这个 32 位记录作为 32 位写入流或从中读取,观察所有位域位置?想象一下,我正在通过 RS-232 端口与微控制器通信,每个位都需要在正确的时间准确地位于正确的位置。语法 for RAM_Register use record...
似乎对 'Write
如何安排其输出没有影响。
如果我确实提供了自己的 'Read
和 'Write
实现,那么 直接 是否与 'for RAM_Register 使用记录相矛盾...`代码?
您可能必须将实例转换为无符号整数(通过未经检查的转换),然后将无符号整数写入流。 Write
的默认实现忽略了表示子句(另见 RM 13 9/3):
For composite types, the Write or Read attribute for each component is called in canonical order, [...]
所以,添加
with Interfaces; use Interfaces;
with Ada.Unchecked_Conversion;
并将RAM_Register
定义为
type RAM_Register is
record
Opcode : Opcode_Number;
Z : Bit;
C : Bit;
R : Bit;
I : Bit;
Cond : Condition_Number;
Rsvd_1 : Bit;
Rsvd_2 : Bit;
Dest : Operand;
Src : Operand;
end record with Atomic;
procedure Write
(Stream : not null access Ada.Streams.Root_Stream_Type'Class;
Item : RAM_Register);
for RAM_Register'Write use Write;
for RAM_Register use
record
Opcode at 0 range 28 .. 31;
Z at 0 range 27 .. 27;
C at 0 range 26 .. 26;
R at 0 range 25 .. 25;
I at 0 range 24 .. 24;
Cond at 0 range 20 .. 23;
Rsvd_1 at 0 range 19 .. 19;
Rsvd_2 at 0 range 18 .. 18;
Dest at 0 range 9 .. 17;
Src at 0 range 0 .. 8;
end record;
for RAM_Register'Size use 32;
for RAM_Register'Bit_Order use System.High_Order_First;
-----------
-- Write --
-----------
procedure Write
(Stream : not null access Ada.Streams.Root_Stream_Type'Class;
Item : RAM_Register)
is
function To_Unsigned_32 is
new Ada.Unchecked_Conversion (RAM_Register, Unsigned_32);
U32 : Unsigned_32 := To_Unsigned_32 (Item);
begin
Unsigned_32'Write (Stream, U32);
end Write;
这会产生
$ xxd -g1 test.dat
00000000: 01 03 8e 8f ....
注意:位序可能已经颠倒了,因为我不得不评论方面规范for RAM_Register'Bit_Order use System.High_Order_First;