所以我是Ada的新手,我试图在其中编写内核,但我似乎无法找到有关如何正确执行此操作的任何有用的信息。在C中,我会写:
unsigned char* videoram = (char*) 0xB8000;
videoram[0] = 65;
直接访问视频ram并写一个'它。我听说我需要使用Ada数组和其他实用工具在Ada中以类型安全的方式执行此操作。这种Ada编程有什么好的资源吗?
答案 0 :(得分:5)
您可以使用'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范围之外写字。
答案 1 :(得分:4)
如果使用地址属性(即对于Object'Address使用...),则应使用System.Storage_Elements中的To_Address()函数,因为Address类型不必是整数。 Ada参考手册仅说明:
“地址是一种明确的,无限制的类型,具有可预先标记的初始化”
而对于System.Storage_Elements中的Integer_Address类型,它指出:
“Integer_Address是一个(带符号或模块化)整数子类型.To_Address和To_Integer在此类型和地址之间来回转换。”
所以,你应该真的使用:
for Object'Address使用To_Address(16#B8000#);
从TED的答案中要指出的最后一点是,如果您担心使用此方法进行对象初始化,只需在声明后添加一个pragma Import(Ada,your_object),以便禁止默认初始化。
答案 2 :(得分:2)
实际上有两种方式。
一种是设置指向您想要使用的地址的指针,并通过指针访问该对象。
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中具有初始化代码的任何字段都将重新初始化。此外,人们很容易过度使用(滥用)该功能来对所有地方的对象进行别名,这对优化器来说既困难又对维护程序员来说很难。
指针方法只是告诉编译器假设给定的地址包含你告诉它的结构,恕我直言就是你想要发生的。