我目前正在編寫一個基本的操作系統作爲一個學習項目。爲此我使用了gcc 4.9.2交叉編譯器。 當試圖使用存儲器映射的I/O I偶然發現C指針(或可能存儲器映射I/O),我無法理解的行爲。 當通過下面的代碼直接訪問I/O存儲器,I得到預期的結果,這是一個「AB」在黑色背景上的淺灰色字體的左上角。奇怪的行爲映射I/O
*((uint16_t *)0xB8000) = 0x0741;
*((uint16_t *)0xB8002) = 0x0742;
但是試圖通過使用偏移添加2基地址來操縱存儲器當結果沒有作爲在第二但在第三位置預期的「A」。
*((uint16_t *)0xB8000 + 2) = 0x0741;
添加1而不是2打印第二個位置的字母,但我不明白爲什麼。由於每個字母(在MMIO中)由2個字節的數據組成,因此我認爲我需要將我寫入的內存地址增加2,以便爲下一個字符。 (正如我在第一次做直接寫入0xB8002) 爲了嘗試和理解這種行爲,我做了一個單獨的C程序的一些測試,但無法複製這種行爲: (注:此代碼被編譯使用普通的gcc 4.8 0.2)
#include <stdint.h>
#include <stdio.h>
void main(void) {
printf("0xB8000 + 1 = %x\n", 0xB8000 + 1);
printf("&(*(uint16_t *)(0xB8000 + 1)) = %x\n", (uint32_t)&(*(uint16_t *)(0xB8000 + 1)));
}
這個程序產生的輸出如下:
0xB8000 + 1 = b8001
&(*(uint16_t *)(0xB8000 + 1)) = b8001
我認爲我缺少某種C指針的行爲,這將導致保理在由寫入的數據的大小一份聲明。這是這種情況還是我有忽略的另一個原因?
問候,Kenshooak
你可能會受益於重新讀指針運算基礎(總是由基本型縮放)。或者,也許運算符優先級(強制轉換優先級高於「+」)。 – Deduplicator 2015-02-11 18:23:34
此外,您可能需要使用'volatile'這裏,以確保編譯器不自作聰明,優化作業了。 – 2015-02-11 18:49:49