Я работаю над частью программного обеспечения, которое генерирует ассемблерный код во время выполнения. Например,
вот очень простая функция, которая генерирует ассемблерный код для вызова функцииGetCurrentProcess
(для Win64 ABI):
void genGetCurrentProcess( char *codePtr, FARPROC addressForGetCurrentProcessFunction )
{
#ifdef _WIN64
// mov rax, addressForGetCurrentProcessFunction
*codePtr++ = 0x48
*codePtr++ = 0xB8;
*((FARPROC *)codePtr)++ = addressForGetCurrentProcessFunction;
// call rax
*codePtr++ = 0xFF;
*codePtr++ = 0xD0;
#else
// mov eax, addressForGetCurrentProcessfunction
*codePtr++ = 0xB8;
*((FARPROC *)codePtr)++ = addressForGetCurrentProcessFunction;
// call eax
*codePtr++ = 0xFF;
*codePtr++ = 0xD0;
#endif
}
Обычно я бы использовал встроенный ассемблер, но, увы, это невозможно с 64-битных компиляторов MSVC больше нет. Пока я на этом - этот код должен работать с MSVC6 до MSVC10, а также с MinGW. Есть еще много функций, таких как genGetCurrentProcess
, все они выдают ассемблерный код, и многие из них получают указатели на функции, которые будут вызываться в качестве аргументов.
Раздражает то, что изменение этого кода чревато ошибками, и нам приходится позаботиться о вещах, специфичных для ABI, вручную (например, резервирование 32-байтового пространства в стеке перед вызовом функций для сброса регистров).
Итак, мой вопрос: могу ли я упростить этот код для генерации кода на ассемблере во время выполнения? Я надеялся, что смогу как-то напрямую написать код на ассемблере (возможно, во внешнем файле, который затем собирается с использованием ml
/ ml64
), но мне не ясно, как это будет работать, если некоторые байты в собранном коде известны только во время выполнения (например, значение addressForGetcurrentProcessFunction
в приведенном выше примере).Может быть, можно собрать некоторый код, но присвоить «метки» определенным местам в коде, чтобы я мог легко изменить код во время выполнения, а затем скопировать его в свой буфер?