对于非常低级别的优化目的,如果我可以将编译后的函数直接存储在变量中,这对我很有用,not指向函数的指针。也就是说,如果我有一个函数 foo,我想创建一个足够大的 char 缓冲区来容纳为 foo 生成的机器指令,然后能够通过某种方式告诉 C 将执行跳转到该缓冲区的内容来有效调用 foo (假设我有一个编译器内在功能来确保字符缓冲区针对我的体系结构正确对齐)。理想情况下,我想这样做,将程序集的使用量保持在最低限度(我意识到可能需要一些程序集)。
到目前为止,我最好的解决方案是编译一个程序,该程序只有我想用 GCC 汇编的功能,然后编译为机器代码,然后使用输出程序集中的地址从可执行文件中提取所需的机器代码,然后手动填充缓冲区与我的程序中的缓冲区相同,然后使用内联汇编跳转到缓冲区的起始地址。但这比我想要的更麻烦和手动工作。
我不需要在运行时编译新函数,只需让缓冲区包含与运行时不同的已编译函数相对应的指令即可。例如。我可能有 3 个编译函数和 1 个缓冲区。这 3 个函数在编译时是已知的,但在运行时缓冲区可能在不同时间对应于这 3 个函数中的任何一个。
编辑:为了澄清将会获得什么:我有一个该缓冲区将成为其成员的结构,以及指向该结构实例的各种指针。每个结构体的缓冲区可能包含不同的编译函数。如果我要使用函数指针而不是缓冲区,则必须加载结构体的函数指针,然后取消引用函数指针。有了缓冲区,我可以将程序计数器跳转到结构体基址的偏移量(缓冲区的相对位置)。这是少了一层间接性。对于非常小的函数,这可以节省成本。
编辑2:进一步澄清:
使用函数指针:
- 从 &struct+offsetof(pointer) 加载指针
- 跳转到指针所包含的位置
使用包含机器代码的缓冲区:
- 跳转到 &struct+offsetof(buffer)
第二个是步骤少。
请注意,大多数现代体系结构都支持内存页面的不执行保护,并且具有一定意义的操作系统会利用它来确保安全。这意味着您不能使用例如堆栈内存或随机分配的内存来存储此代码;您需要使用例如调整权限VirtualProtect
在 Windows 或mprotect
在Unices上。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)