所以我是 Ada 的新手,我正在尝试在其中编写一个内核,但我似乎找不到任何关于如何正确执行此操作的好信息。在 C 中,我会写:
unsigned char* videoram = (char*) 0xB8000;
videoram[0] = 65;
直接访问视频RAM并向其写入"a"。我听说我需要使用 Ada 数组和其他编译指示才能在 Ada 中以类型安全的方式执行此操作。这种 Ada 编程有什么好的资源吗?
'Address
属性:
Videoram : String (1 .. Videoram_Size);
for Videoram'Address use 16#B8000#;
-- ...
Videoram (1) := 'a';
如果你不想使用字符串和字符,你可以定义你自己的数据类型,比如:
type Byte is mod 2**8; -- unsigned char
type Byte_Array is array (Natural range <>) of Byte;
Videoram : Byte_Array (0 .. Videoram_Size - 1);
for Videoram'Address use 16#B8000#;
-- ...
Videoram (0) := 65;
顺便说一句,您甚至可以对索引进行范围检查,因此您不能在 Videoram 范围之外写入。
如果使用地址属性(即用于 Object'Address 使用 ...),则应使用 System.Storage_Elements 中的 To_Address() 函数,因为地址类型不必是整数。Ada 参考手册仅指出:
"地址是一个确定的、非限制的类型,具有可预先阐述的初始化"
而对于 System.Storage_Elements 中的Integer_Address类型,它指出:
"Integer_Address是一个(有符号或模块化)整数子类型。To_Address和To_Integer在此类型和地址之间来回转换。
因此,您确实应该使用:
对于对象'地址使用 To_Address( 16#B8000# );
从 T.E.D 的回答中要指出的最后一件事是,如果您担心使用此方法进行对象初始化,只需在声明后添加一个杂注 Import( Ada, your_object ),以便禁止默认初始化。
实际上有两种方法。
一种是设置指向要使用的地址的指针,并通过指针访问对象。
type Video_RAM_Pointer is access all My_Video_Ram_Struct;
package Convert is new System.Address_To_Access_Conversions (Video_RAM_Pointer);
Video_RAM : constant Video_RAM_Pointer := Convert.To_Access (16#B8000#);
另一种是将数据直接叠加在位置顶部。
Video_RAM : My_Video_RAM_Struct;
for Video_RAM'address use at 16#B8000#;
一般来说,我更喜欢使用前者。除其他问题外,后者算作声明,这意味着每次声明覆盖时,My_Video_RAM_Struct中具有初始化代码的任何字段都将重新初始化。此外,人们很容易过度使用(滥用)该功能来到处为对象着色,这对优化器和维护程序员来说既困难又困难。
指针方法只是告诉编译器假设给定的地址包含您告诉它的结构,恕我直言,这正是您想要发生的。