stream - Ada - 如何显式打包位字段记录类型?

标签 stream record ada bit-fields

请考虑以下实验性 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在这里: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 端口上与微 Controller 通信,每个位都需要在正确的时间准确地位于正确的位置。语法 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;

关于stream - Ada - 如何显式打包位字段记录类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58493193/

相关文章:

java - 方法可能无法在异常时关闭流

java - 将 SLF4J 日志重定向到 JavaFX 中的 TextArea

Java.nio Files.walk() Java 8 列出并统计所有文件和目录

ada - -gnatyo 实际上执行什么样式检查?

sockets - 检索后从套接字流阻止中读取

java - 在 Java 中将远程文件通过 HTTP 转换为输入流

ruby - 在 ruby , window 中录制声音

android - 无法使用 Samsung Galaxy S2 进行录音,但可以通过麦克风使用其他手机进行录音

arrays - 如何在 f# 中将记录字段定义为数组?

c++ - 在 VXWorks 6.7(workspace-4) 中由 c++(UsrAppInit) 执行的 ADA 文件有问题吗?