В последнее время я писал некоторые монтажные инъекции x86 для игрового мода, но поскольку большая часть моего рабочего процесса связана с написанием и сбором пользовательских подпрограмм вручную, я был стремясь перейти к более надежному решению.MASM Mov с/на адрес оперативной памяти
Встроенный ассемблер Microsoft выглядит как хороший выбор, но я столкнулся с чем-то вроде ограничения, которое, похоже, имеет.
Всякий раз, когда я пишу инструкцию, которая включает в себя адрес прямой памяти (игра использует макет фиксированного адресного пространства), ассемблер молча преобразует его в непосредственное значение.
Например, в MASM:
mov ecx, 0xCCCCCCCC => B9 CC CC CC CC
mov ecx, [0xCCCCCCCC] => B9 CC CC CC CC*
* Should be: 8B 0D CC CC CC CC
В этом случае оба собранных инструкции загружаются ECX с непосредственным значением 0xCCCCCCCC, хотя второй следует извлечение значения из непосредственного адреса 0xCCCCCCCC
Обратите внимание, что можно использовать переменную с именем таким образом:
mov ecx, [myInt]
Которая будет собираться в инструкцию выборки памяти 8B 0D, но также добавляет операнд в таблицу перемещения модуля и не позволяет специфицировать произвольные адреса.
Попытка обмануть ассемблер с чем-то вроде
mov ecx, [myInt-myInt+0xCCCCCCCC]
приводит также в адрес рассматривается как непосредственное значение.
Вполне возможно можно пойти с:
mov ecx, 0xCCCCCCCC
mov ecx, [ecx]
Какие будут собираться правильно и демонстрировать правильное поведение, но теперь я раздутой мой размер впрыска от 2 лишних байтов. Поскольку я работаю при довольно жестких пространственных ограничениях, это неприемлемо, и я бы предпочел не использовать пещеру кода, где мне не нужно.
Самое смешное, что что-то в C нравится:
register int x;
x = *(int*)(0xCCCCCCCC)
Счастливо компилирует
mov ecx, [0xCCCCCCCC] => 8B 0D CC CC CC CC
Это немного странно видеть более низкий уровень языка имеют больше ограничений, установленных на нем, чем выше уровня. То, что я пытаюсь сделать, выглядит довольно разумным для меня, так же как и кто-нибудь знает, имеет ли MASM скрытый способ использования фиксированных адресов памяти при чтении из памяти?
MASM не выполняет арифметику между метками? Это только внутри эффективного адреса, или оно также применяется в выражении, используемом как немедленное? Я мог представить, что это не работает, если метки были «extern», поэтому разница была доступна только как время ссылки, а не время сборки. Вы должны иметь возможность использовать локальные метки или любую существующую метку (например, имя текущей функции). –
Извините, это была моя ошибка. Я проводил немного тестирования взад и вперед между MASM и встроенным ассемблером VS. Встроенный ассемблер более ограничен, поэтому он не поддерживает арифметику меток, но сам MASM в порядке. Тем не менее, эффективный адрес по-прежнему заканчивается тем, что рассматривается как немедленное значение. –
Я думаю, что Ross Ridge дает довольно хороший ответ на аналогичный вопрос MASM в этом SO-ответе: http://stackoverflow.com/a/25130189/3857942 –