Я работаю над программным обеспечением, которое генерирует код ассемблера во время выполнения. Например,
здесь очень простая функция, которая генерирует код ассемблера для вызова функции 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
в приведенном выше примере). Может быть, возможно собрать какой-то код, но назначить "метки" определенным местам в коде, чтобы я мог легко изменить код во время выполнения, а затем скопировать его в мой буфер?