Я программирую JIT-компилятор, который должен вызывать функции c ++ из скомпилированного кода asm.
Я до сих пор работаю на Windows x64 и реализовал соглашение о вызовах от Microsoft. (https://msdn.microsoft.com/en-us/library/ms235286.aspx)
Это работает, пока это не так.
Если вызываемая функция проста и вызывает только простые функции (использует подмножество типа C), она всегда работает.
Если вызываемая функция вызывает другие функции, например, «std :: cout», он работает, если он скомпилирован для Debug, но не для выпуска.
Если вызываемая функция вызывает некоторые функции VULKAN, она вообще не работает.
Пример кода, который генерирует jit-компилятор:
sub %10 r64(4), imm8(48)
mov %1 r64(0), %6 r64(1)
mov %2 r64(2), m64[%1]
mov %3 r32(1), imm32(5)
mov ST: m64 +40, %2 r64(2)
call m64 <call PrintInt()>
mov %2 r64(2), ST: m64 +40
mov m32[%2] +16, %4 r32(0)
mov %5 r32(0), imm32(-2)
add %10 r64(4), imm8(48)
ret
Объект (сброс в https://www.onlinedisassembler.com/odaweb/ с x86-64):
48 83 EC 30 48 89 C8 48 8B 10 B9 05 00 00 00 48 89 54 24 28 FF 15 D6 FF FF FF 48 8B 54 24 28 89 42 10 B8 FE FF FF FF 48 83 C4 30 C3
Вызываемая функция так же проста, как (не в выпуске):
int PrintInt(int nr) {
std::cout << nr << std::endl; // error
return nr;
}
Ошибка:
«Исключение, выданное по адресу 0x000007FEE3693D39 (msvcp140.dll) в test.exe: 0xC0000005: расположение чтения нарушения доступа 0x0000000000000000».
Есть идеи, что мне не хватает?
Отредактируйте разборку с моими комментариями
sub rsp, 0x30 // subtract 48 bytes from stack pointer to get 6 slots of space
mov rax, rcx // rcx is a pointer parameter
mov rdx, QWORD PTR [rax] // load pointer from [rax]
mov ecx, 0x5 // imm 5 into ecx for function call
mov QWORD PTR [rsp+0x28], rdx // save rdx for after function call on the stack
call QWORD PTR [..] // function call
mov rdx, QWORD PTR [rsp+0x28] // get rdx back from stack
mov DWORD PTR [rdx+0x10], eax // save result
mov eax, 0xfffffffe // -2 in eax (return value)
add rsp, 0x30 // restore stack ptr (free)
ret
СТЕК:
.... start
[XXX] used to save rdx
[ ] unused
[ s ]
[ s ]
[ s ]
[ s ] shadow space
.... call
Я резервирую 6 слотов (8 байт), поэтому получаю 16 байт при выравнивании вызовов.
Спасибо за любую помощь.
Задача ещё не решена.
Других решений пока нет …