В настоящее время я работаю над написанием базовой операционной системы в качестве учебного проекта. Для этой цели я использую кросс-компилятор gcc 4.9.2. При попытке использовать ввод-вывод с отображением памяти я наткнулся на поведение указателей C (или, возможно, ввод-вывод с отображением памяти), которое я не могу понять. При прямом доступе к памяти ввода-вывода с помощью следующего кода я получаю ожидаемый результат, который представляет собой «AB» в верхнем левом углу светло-серым шрифтом на черном фоне.
*((uint16_t *)0xB8000) = 0x0741;
*((uint16_t *)0xB8002) = 0x0742;
Однако при попытке манипулировать памятью с помощью смещения, добавляющего 2 к базовому адресу, результатом будет не «А» во второй, а в третьей позиции, как ожидалось.
*((uint16_t *)0xB8000 + 2) = 0x0741;
Добавление 1 вместо 2 выводит букву на вторую позицию, однако я не понимаю, почему. Поскольку каждая буква (в MMIO) состоит из 2 байтов данных, я бы предположил, что мне нужно увеличить адрес памяти, в который я пишу, на 2 для следующего символа. (Как я сделал сначала, написав напрямую в 0xB8002). Чтобы попытаться понять это поведение, я провел некоторое тестирование в отдельной программе на C, но не смог воспроизвести это поведение: (Примечание: этот код был скомпилирован с использованием обычного gcc 4.8.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, которое вызывает факторизацию размера данных, которые записываются оператором. Так ли это или есть другая причина, которую я упустил из виду?
С уважением, Кеншуак.
+
). - person Deduplicator   schedule 11.02.2015volatile
, чтобы убедиться, что компилятор не пытается быть умным и оптимизировать присваивания. - person Tim Čas   schedule 11.02.2015