所以我是Ada的新手,我試圖編寫一個內核,但我似乎無法找到任何有關如何正確執行此操作的良好信息。在C中,我會寫:如何直接在Ada中訪問內存地址?
unsigned char* videoram = (char*) 0xB8000;
videoram[0] = 65;
直接訪問視頻ram並寫入'a'。我聽說我需要使用Ada數組和其他編譯指令在Ada中以類型安全的方式執行此操作。這種Ada編程有沒有很好的資源?
所以我是Ada的新手,我試圖編寫一個內核,但我似乎無法找到任何有關如何正確執行此操作的良好信息。在C中,我會寫:如何直接在Ada中訪問內存地址?
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範圍之外進行編寫。
有沒有類型安全的方式來定義一個2字節類型的第一個字節是一個字符,第二個彩色字節?因爲這是視頻內存每個字符的實際格式。 – MarkHammons
@MarkHammons我有點困惑。你的意思是「視頻內存每個字符_pair_」? (上次我檢查了一個字節是一個字符的大小!) – NWS
@NWS是的,每個字符,videoram需要一對字節。第一個字節是實際字符,第二個字節定義背景和前景色。例如,0x00是黑色的。在C中,「 videoram [0] = 65; videoram [1] = 0x00; videoram [2] = 66; videoram [3] = 0x00;」用黑色背景打印黑色的ab。 – MarkHammons
實際上有兩種方法。
一個是設置一個指向你想要使用的地址的指針,並通過指針訪問該對象。
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中的任何字段都將重新初始化。此外,人們很容易濫用(濫用)該功能,以便在整個地方使用別名對象,這對優化器來說都很難,對維護程序員來說也很難。
該指針方法只是告訴編譯器假定給定的地址持有你告訴它的結構,恕我直言,這正是你想要發生的。
如果您使用地址屬性(即用於Object'Address use ...),則應使用System.Storage_Elements中的To_Address()函數,因爲地址類型不必是整數。 ADA的參考手冊只規定:
「地址是一個明確的,nonlimited型與preelaborable初始化」
而對於Integer_Address類型它指出System.Storage_Elements:
「Integer_Address是(簽名或模塊化)整數子類型To_Address和To_Integer在此類型和地址之間來回轉換。「
所以,你應該使用:
爲Object'Address使用To_Address(16#B8000#);
T.E.D的回答中最後要指出的一點是,如果您關注使用此方法進行對象初始化,只需在聲明後添加一個雜注導入(Ada,your_object),以便禁止默認初始化。
這可能是作爲對其他兩個答案的評論完成的。然而,你是新的,可以使用代表,所以+1。 :-) –
oenones的進一步思考答案(和我的貢獻) - 如果您只進行文本處理並知道屏幕邊界,則可以將您的數組定義爲2D數組,並且能夠直接訪問行和列位置而無需計算內存偏移每次。 (只是要小心行或列的主要問題(先到先得以及如何映射到你的內存段) – NWS