本帖最后由 福仔 于 2023-6-27 12:30 编辑
起因:
因为要写一个汇编查看器, 所以需要弄一个反汇编库
百度搜索后, 发现这个库还不错, 于是跟着搜到的资料进行编译
《三个反汇编库的简单介绍和使用》 我是跟着这篇文章编译的
然后编译成静态库后, 也出现了帖子里的错误
于是自己鼓捣一下, 发现就是 BEA_ENGINE_STATIC 这个宏的问题
于是自己尝试一下编译, 不依靠CMake
整个编译流程大致的方向
- 创建静态库项目
- 把 src\BeaEngine.c 这个文件加入到项目中
- 编译...
大概的流程就这么简单
但是本帖是保姆级的编译流程, 所以一些细节就都拿出来讲
1. 创建项目
输入名字选择保存目录后点击创建就行
创建后把几个默认创建的文件删除
3. 尝试编译
加入后开始尝试第一次编译
报了下面的错误, 这个错误是预编译头的错误, 设置里关闭就行
关闭预编译头
第二次尝试编译
又报了下面的错误, 这个是找不到包含文件, 设置里加一下包含目录
设置包含目录
第三次尝试编译
加入包含目录后再次尝试编译, 报了下面的错误, 这个是安全函数的问题, 预处理器里加上 _CRT_SECURE_NO_WARNINGS 就行
加入 _CRT_SECURE_NO_WARNINGS 宏
第四次尝试编译
再次尝试编译, 编译成功了, 但是出现了下面的警告
双击进来看看警告的原因是什么
通过上面的图能看到, 函数的声明多了一个 BEA_API , 定义这里没有 BEA_API
跳转到 BEA_API 的定义位置
#if !defined(BEA_ENGINE_STATIC)
#if defined(BUILD_BEA_ENGINE_DLL)
#define BEA_API bea__api_export__
#else
#define BEA_API bea__api_import__
#endif
#else
#define BEA_API
#endif
这里可以看到, 如果没有定义 BEA_ENGINE_STATIC , 那里面就会根据 BUILD_BEA_ENGINE_DLL 这个宏来定义 BEA_API
现在 BEA_ENGINE_STATIC 没有定义, BUILD_BEA_ENGINE_DLL 也没有定义
所以最后是定义了#define BEA_API bea__api_import__
然后再去看 bea__api_import__ 的定义
# define bea__api_import__ __declspec(dllimport)
bea__api_import__ 定义成了 __declspec(dllimport)
所以, 如果不加入 BEA_ENGINE_STATIC 的话, 函数声明就变成了
__declspec(dllimport) int __bea_callspec__ Disasm (PDISASM pMyDisasm);
而定义是 int __bea_callspec__ Disasm (PDISASM pMyDisasm);
所以就出现了DLL 链接不一样的警告
既然知道了原因, 那就加上这个宏 BEA_ENGINE_STATIC
第五次尝试编译
加入后再次尝试编译, 0警告, 0错误, 完美....
到这里就已经编译完成了, 其实这个编译和CMake编译的结果差不多
创建测试项目
下面来创建一个程序测试调用, 因为根据我看的那篇文章报错的是调用程序报错
测试程序代码
新建后做好以上配置后, 写上以下代码作为测试程序
#include <iostream>
#include <Windows.h>
#include <beaengine/BeaEngine.h>
// 反汇编字节数组
void DisassembleCodeByte(BYTE* ptr, int len)
{
DISASM Disasm_Info;
char* end_offset = (char*)ptr + len;
(void)memset(&Disasm_Info, 0, sizeof(DISASM));
Disasm_Info.EIP = (UInt64)ptr;
Disasm_Info.Archi = 0; // 1 = 表示反汇编32位 / 0 = 表示反汇编64位
Disasm_Info.Options = MasmSyntax; // 指定语法格式 MASM
while ( !Disasm_Info.Error )
{
Disasm_Info.SecurityBlock = (UInt64)end_offset - Disasm_Info.EIP;
if ( Disasm_Info.SecurityBlock <= 0 )
break;
len = Disasm(&Disasm_Info);
switch ( Disasm_Info.Error )
{
case OUT_OF_BLOCK:
break;
case UNKNOWN_OPCODE:
Disasm_Info.EIP += 1;
Disasm_Info.Error = 0;
break;
default:
printf("%s \n", &Disasm_Info.CompleteInstr);
Disasm_Info.EIP += len;
}
}
}
int main()
{
int address = 0;
// 从 &address 这个变量地址开始的位置, 打印100个字节转换成汇编的结果
DisassembleCodeByte((BYTE*)( &address ), 100);
std::cout << "Hello World!\n";
}
加入包含目录后编译测试调用程序, 然后就出现了文章中提到的错误
根据上面我们说的函数声明那, 如果没有定义 BEA_ENGINE_STATIC 宏
那么函数声明是 __declspec(dllimport) int __bea_callspec__ Disasm (LPDISASM pDisAsm); 这样的
我们需要把 __declspec(dllimport) 这个去掉
怎么去掉呢? 是不是跟上面一样, 加上 BEA_ENGINE_STATIC 这个宏就行了
这里直接加入了
|