Nano Hash - криптовалюты, майнинг, программирование

Разница в приращении указателя ч/б 32-бит и 64-бит

Я пытался запустить некоторые драйверы, закодированные для 32-разрядной версии Vista (x86), на 64-разрядной версии win7 (amd64), но они не запускались. После долгих отладок и испытаний я заставил его работать над последним, но я не знаю, почему он работает. Вот что я сделал:

Во многих местах указатели буфера указывали на массив структур (разные в разных местах), и для их увеличения в некоторых местах использовался такой тип оператора:

ptr = (PVOID)((PCHAR)ptr + offset);

И в некоторых местах:

ptr = (PVOID)((ULONG)ptr + offset);

Второй возвращал мусор, поэтому я заменил их всех на 1-й. Но я нашел много образцов драйверов в сети после второго. Мои вопросы:

  1. Где определяются эти макросы (гугл не сильно помог)?
  2. Я понимаю, что все макросы P_ являются указателями, почему указатель был приведен к ULONG? Как это работает на 32-битной?
  3. Очевидно, что PCHAR изменяет ширину в зависимости от среды. Вы знаете, где найти документацию для этого?
25.11.2010

Ответы:


1
  1. они должны быть определены в WinNT.h (они есть в SDK, DDK под рукой нет)
  2. ULONG — беззнаковая длинна; в 32-битной системе это размер указателя. Таким образом, указатель может быть преобразован туда и обратно в ULONG без потерь, но не в 64-битной системе (где приведение значения усекает его). Люди приводят к ULONG, чтобы получить арифметику указателя на базе байтов (даже несмотря на то, что это имеет неопределенное поведение, как вы узнали)
  3. Арифметика указателей всегда работает в единицах базового типа, то есть в CHAR для PCHAR; это соответствует байтовой арифметике
  4. Любая книга по C должна подробно описывать точную семантику арифметики указателей.
25.11.2010

2

Причина, по которой этот код не работает в 64-разрядной версии, заключается в том, что он приводит указатели к ULONG. ULONG — это 32-битное значение, а указатели на 64-бит — это 64-битные значения. Таким образом, вы будете усекать указатель всякий раз, когда используете приведение ULONG.

Приведение PCHAR, предполагая, что PCHAR определено как char *, прекрасно, при условии, что намерение состоит в том, чтобы увеличить указатель на явное количество байтов.

Оба макроса имеют одинаковое назначение, но только один из них действителен, когда указатели больше 32 бит.

Арифметика указателей работает следующим образом. Если у вас есть:

T *p;

и вы делаете:

p + n;

(где n — число), то значение p изменится на n * sizeof(T).

Чтобы привести конкретный пример, если у вас есть указатель на DWORD:

DWORD *pdw = &some_dword_in_memory;

и вы добавляете к нему один:

pdw = pdw + 1;

тогда вы будете указывать на следующий DWORD. Адрес, на который указывает pdw, увеличится на sizeof(DWORD), то есть на 4 байта.

Макросы, о которых вы упоминаете, используют приведения, чтобы смещения адресов, которые они применяют, умножались на разные суммы. Обычно это делается только в низкоуровневом коде, которому был передан буфер BYTE (или char или void), но известно, что данные внутри него на самом деле имеют другой тип.

25.11.2010
  • Перечитывая ваш вопрос, я заметил, что он приводится к ULONG, а не к ULONG*, поэтому я добавил часть вверху своего ответа, которую я считаю самой важной частью. Остальное - просто справочная информация. 25.11.2010

  • 3

    ULONG определяется в WinDef.h в Windows SDK и всегда имеет значение 32- бит, поэтому, когда вы приводите 64-битный указатель к ULONG, вы усекаете указатель до 32 бит.

    25.11.2010
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

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

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..