我遇到了一个非常特殊的问题。对于虚拟机,我需要将指令函数中的代码复制到一个 ubyte 数组中,然后执行这个数组(技术类似于 gcc 中的内联宏 vm),基本上它的工作原理是这样的:
__gshared void * sp = null, sb = null; //stack pointer and stack base
__gshared void add() //the function is just there to access the instruction code
{
asm{db "INSTRUCTIONCODESTART";} //this is a key to know where the instruction code starts
//instruction code here (sample instruction add, pops 2 values from the stack and pushes its result)
sp += 4;
*cast(uint*)sp += *cast(uint*)(sp - 4);
asm{db "INSTRUCTIONCODEEND";} //this is a key to know where instruction code ends
}
在 Init 方法中,每个指令代码都有自己的缓冲区,缓冲区中包含 INSTRUCTIONCODESTART 和 INSTRUCTIONCODEEND 键之间的每个字节。我通过 windows VirtualProtect 调用使这个数组可执行。
到目前为止,一切都按预期工作,但是当我尝试将函数调用作为指令进行时,我会收到错误消息。
__gshared void testcall(){}
__gshared void call()
{
asm{db "INSTRUCTIONCODESTART";} //this is a key to know where the instruction code starts
//instruction code here (just calls a D function)
testcall(); //this somehow throws an error
asm{db "INSTRUCTIONCODEEND";} //this is a key to know where instruction code ends
}
顺便说一句,我使用以下代码测试了说明
void instructiontest()
{
uint dummy;
ubyte[] buf = getFunctionCode(&add) ~ 0xC3; //gets code of instruction, appends 0xC3 at it ("ret" instruction, for test purposes only to see if it returns to the D code without errors)
VirtualProtect(cast(void*)buf, buf.length, PAGE_EXECUTE_READWRITE, &dummy); //makes it executeable
dummy = cast(uint)&buf[0];
asm
{
call dummy[EBP];
}
print("instruction worked without errors!");
}
到目前为止,每条简单指令(add、mul、sub、push0、push1、...)都有效,但如果我尝试通过函数调用获取指令的代码,则会引发错误
我会很高兴并且非常感谢任何帮助。(顺便说一句,我需要在指令中调用函数,以便让脚本语言与 D 通信)