在 Ada 中将地址拆分并转换为不同的整数

Rot*_*er2 1 casting bit-manipulation ada

要与某个硬件(在本例中为 x86 GDT 的 TSS 条目)接口,需要在内存中使用以下结构:

type UInt32 is mod 2 ** 32;
type UInt16 is mod 2 ** 16;
type UInt8  is mod 2 ** 8;

type TSSEntry is record
   Limit       : UInt16;
   BaseLow16   : UInt16;
   BaseMid8    : UInt8;
   Flags1      : UInt8;
   Flags2      : UInt8;
   BaseHigh8   : UInt8;
   BaseUpper32 : UInt32;
   Reserved    : UInt32;
end record;
for TSSEntry use record
   Limit       at 0 range 0  .. 15;
   BaseLow16   at 0 range 16 .. 31;
   BaseMid8    at 0 range 32 .. 39;
   Flags1      at 0 range 40 .. 47;
   Flags2      at 0 range 48 .. 55;
   BaseHigh8   at 0 range 56 .. 63;
   BaseUpper32 at 0 range 64 .. 95;
   Reserved    at 0 range 96 .. 127;
end record;
for TSSEntry'Size use 128;
Run Code Online (Sandbox Code Playgroud)

在把一些C代码翻译成Ada的时候,遇到了几个问题,网上也找不到很多资源。C 代码段是:

type UInt32 is mod 2 ** 32;
type UInt16 is mod 2 ** 16;
type UInt8  is mod 2 ** 8;

type TSSEntry is record
   Limit       : UInt16;
   BaseLow16   : UInt16;
   BaseMid8    : UInt8;
   Flags1      : UInt8;
   Flags2      : UInt8;
   BaseHigh8   : UInt8;
   BaseUpper32 : UInt32;
   Reserved    : UInt32;
end record;
for TSSEntry use record
   Limit       at 0 range 0  .. 15;
   BaseLow16   at 0 range 16 .. 31;
   BaseMid8    at 0 range 32 .. 39;
   Flags1      at 0 range 40 .. 47;
   Flags2      at 0 range 48 .. 55;
   BaseHigh8   at 0 range 56 .. 63;
   BaseUpper32 at 0 range 64 .. 95;
   Reserved    at 0 range 96 .. 127;
end record;
for TSSEntry'Size use 128;
Run Code Online (Sandbox Code Playgroud)

这是我试图将其翻译成的 Ada 代码:

TSS : TSSEntry;

procedure loadTSS (Address : System.Address) is
begin
   TSS.BaseLow16   := Address; --  How would I downcast this to fit in the 16 lower bits?
   TSS.BaseMid8    := Shift_Right(Address, 16); -- Bitwise ops dont take System.Address + downcast
   TSS.Flags1      := 2#10001001#;
   TSS.Flags2      := 0;
   TSS.BaseHigh8   := Shift_Right(Address, 24); -- Same as above
   TSS.BaseUpper32 := Shift_Right(Address, 32); -- Same as above
   TSS.Reserved    := 0;
end loadTSS;
Run Code Online (Sandbox Code Playgroud)

我如何能够显示我在代码中突出显示的问题?在这种情况下,初学者可以使用任何资源来寻求帮助吗?提前致谢!

Nik*_*sti 7

使用包 System.Storage_Elements 中的 To_Integer 函数将地址转换为整数,然后将该整数转换为 Interfaces.Unsigned_32 或 Unsigned_64(以合适的为准),以便您可以使用移位操作来提取位域。

除了移位和掩码操作之外,您当然可以使用除法和“mod”将整数分开,而无需转换为接口类型。