Как я могу получить доступ к вектору прерывания, расположенному в местоположении 0 машины?


Как я могу получить доступ к вектору прерывания, расположенному в местоположении 0 машины? Если я установлю указатель на 0, компилятор может перевести его в некоторое ненулевое внутреннее значение нулевого указателя.

3 2

3 ответа:

Вы правы, что в зависимости от вашей реализации C внутренний нулевой указатель не может быть равен 0. Но обычно так и есть. Если вы хотите быть очень безопасным, вы можете ввести значение или использовать memset().

uintptr_t zerobits = 0;
void *pointer1 = (void *)zerobits;

Или:

void *pointer2;
memset(&pointer2, 0, sizeof pointer2);

Если вы работаете в домене, где вам нужно читать/записывать векторы по нулевому адресу (я предполагаю, что вы находитесь на какой-то встроенной системе?), то вы обнаружите, что многое из того, что вы делаете, выходит за рамки общей прямолинейной интерпретации стандарта "с".

Можно с уверенностью предположить, что встроенные компиляторы будут генерировать доступ к адресам, которые вы помещаете в указатели, а не волшебным образом изменять их содержимое.

Однако не всегда можно предположить, что a физический адрес ноль в таблице данных-это то, к чему обращается процессор при чтении/записи адреса ноль. Если в процессоре есть MMU, то вам, возможно, придется пройти через какой-то логический - > физический процесс отображения, и даже если нет полного MMU, многие современные небольшие встроенные процессоры играют в игры с адресным пространством вокруг векторов прерываний (загрузка из флэш-памяти и затем при необходимости переназначение этой части адресного пространства в оперативную память, например.)

Поскольку все, что находится в местоположении 0, очевидно зависит от машины, вы можете использовать любой зависящий от машины трюк, чтобы попасть туда. Прочитайте документацию вашего поставщика. Вполне вероятно, что если для вас вообще имеет смысл получить доступ к местоположению 0, система будет настроена так, чтобы сделать это достаточно легко. Некоторые возможности таковы:

Просто установите указатель на 0. (Это способ, который не должен работать, но если он имеет смысл, он, вероятно, будет работать.) Присвоить целое число 0 в переменная int и преобразует ее в указатель. (Это также не гарантировано, но, вероятно, сработает.) Используйте объединение, чтобы установить биты переменной указателя в 0:

union {
    int u_p;
    int u_i;    / assumes sizeof(int) >= sizeof(int *) */
} p;

p.u_i = 0;

Используйте memset, чтобы установить биты переменной указателя в 0:

memset((void *)&p, 0, sizeof(p));

Объявить внешнюю переменную или массив

extern int location0;

И используйте файл языка ассемблера или какой-либо специальный вызов компоновщика, чтобы организовать, что этот символ ссылается на (то есть переменная помещается в) адрес 0.