Я экспортирую функцию [используя _declspec (dllexport)] из C ++ exe. Функция работает нормально, когда вызывается самой исполняемой программой. Я загружаю этот exe (давайте назовем этот exe1) из другого exe [exe тестового проекта - я назову этот exe2], используя статическое связывание, т.е. я использую файл exe1 .lib при компиляции exe2, а exe2 загружает его в память при запуске так же, как любая длл. Это приводит к сбою функции при выполнении.
Точная проблема обнаружена в разборке для оператора case переключения в функции.
Код сборки, когда exe1 вызывает функцию
switch (dwType)
0040FF84 mov eax,dword ptr [dwType]
0040FF87 mov dword ptr [ebp-4],eax
0040FF8A cmp dword ptr [ebp-4],0Bh
0040FF8E ja $LN2+7 (40FFD2h)
0040FF90 mov ecx,dword ptr [ebp-4]
0040FF93 jmp dword ptr (40FFE0h)[ecx*4]
Рассмотрим последние две инструкции. Mov перемещает переданный аргумент в ecx. В 40EFF0h у нас есть адреса к различным инструкциям для соответствующих заявлений случая. Таким образом, jmp приведет нас к соответствующим инструкциям кейса
Код сборки, когда exe2 вызывает функцию
switch (dwType)
0037FF84 mov eax,dword ptr [dwType]
0037FF87 mov dword ptr [ebp-4],eax
0037FF8A cmp dword ptr [ebp-4],0Bh
0037FF8E ja $LN2+7 (37FFD2h)
0037FF90 mov ecx,dword ptr [ebp-4]
0037FF93 jmp dword ptr [ecx*4+40FFE0h]
Найди что происходит не так? Адреса инструкции . Код был загружен в другое место в памяти. Когда exe1 был скомпилирован, компилятор предположил, что мы всегда будем запускать его, и, следовательно, он всегда будет загружаться в 0x0040000 [как в случае всех окон exes]. Поэтому он жестко запрограммировал в инструкции несколько значений, таких как 40FFE0h. Только во втором случае 40FFE0 столь же хорош, как и нежелательная память, поскольку искомая таблица адресов команд там не находится.
Как я могу решить эту проблему без преобразования exe1 в dll?