5

所以我是 Ada 的新手,我正在尝试在其中编写一个内核,但我似乎找不到任何关于如何正确执行此操作的好信息。在 C 中,我会写:

unsigned char* videoram = (char*) 0xB8000;
videoram[0] = 65;

直接访问视频内存并向其写入“a”。我听说我需要使用 Ada 数组和其他编译指示在 Ada 中以类型安全的方式执行此操作。这种 Ada 编程有什么好的资源吗?

4

3 回答 3

6

您可以使用以下'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 范围之外进行写入。

于 2012-05-30T06:38:06.727 回答
5

如果您使用地址属性(即 Object'Address 使用 ... ),您应该使用 System.Storage_Elements 中的 To_Address() 函数,因为地址类型不必是整数。Ada 参考手册仅说明:

“地址是一个明确的、不受限制的类型,具有可预先加工的初始化”

而对于 System.Storage_Elements 中的 Integer_Address 类型,它指出:

“Integer_Address 是(有符号或模数)整数子类型。To_Address 和 To_Integer 在此类型和地址之间来回转换。”

所以,你真的应该使用:

对于 Object'Address 使用 To_Address( 16#B8000# );

One last thing to point out from T.E.D's answer is that if you are concerned about object initialization using this method, simply add a pragma Import( Ada, your_object ) after the declaration so that default initialization is suppressed.

于 2012-05-31T05:55:43.943 回答
3

其实有两种方式。

一种是设置一个指向要使用的地址的指针,并通过指针访问对象。

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 中具有初始化代码的任何字段都会在您每次声明覆盖时重新初始化。此外,人们很容易过度使用(滥用)该功能以在所有地方给对象起别名,这对优化器和维护程序员来说都是困难的。

指针方法只是告诉编译器假设给定的地址包含您告诉它的结构,恕我直言,这正是您想要发生的。

于 2012-05-30T16:19:39.897 回答