Как упростить генерацию кода во время выполнения?

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

17
задан Alexey Frunze 6 March 2012 в 10:11
поделиться