1# Capstone-Engine API Documentation
2
3| Version | 4.0.2 |
4| ------- | ----- |
5
6**Official API document by [kabeor](https://github.com/kabeor)**
7
8[Capstone Engine](https://github.com/capstone-engine/capstone)是一个支持多种硬件架构的二进制反汇编引擎。
9
10
11## 0x0 开发准备
12
13  Capstone官网: http://www.capstone-engine.org
14
15### 自行编译lib和dll方法
16
17  源码: https://github.com/capstone-engine/capstone.git
18
19  git clone下来
20  文件结构如下:
21
22```
23   .                <- 主要引擎core engine + README + 编译文档COMPILE.TXT24├── arch            <- 各语言反编译支持的代码实现
25│   ├── AArch64     <- ARM64 (aka ARMv8) 引擎
26│   ├── ARM         <- ARM 引擎
27│   ├── EVM         <- Ethereum 引擎
28│   ├── M680X       <- M680X 引擎
29│   ├── M68K        <- M68K 引擎
30|   ├── MOS65XX     <- MOS65XX 引擎
31│   ├── Mips        <- Mips 引擎
32│   ├── PowerPC     <- PowerPC 引擎
33│   ├── Sparc       <- Sparc 引擎
34│   ├── SystemZ     <- SystemZ 引擎
35│   ├── TMS320C64x  <- TMS320C64x 引擎
36│   ├── X86         <- X86 引擎
37│   └── XCore       <- XCore 引擎
38├── bindings        <- 绑定
39│   ├── java        <- Java 绑定 + 测试代码
40│   ├── ocaml       <- Ocaml 绑定 + 测试代码
41│   ├── powershell  <- powershell 绑定 + 测试代码
42│   ├── python      <- python 绑定 + 测试代码
43│   └── vb6         <- vb6 绑定 + 测试代码
44├── contrib         <- 社区代码
45├── cstool          <- Cstool 检测工具源码
46├── docs            <- 文档,主要是capstone的实现思路
47├── include         <- C头文件
48├── msvc            <- Microsoft Visual Studio 支持(Windows)
49├── packages        <- Linux/OSX/BSD50├── suite           <- 项目开发所需工具
51├── tests           <- C语言测试用例
52├── windows         <- Windows 支持(Windows内核驱动编译)
53├── windowsce       <- Windows CE 支持
54└── xcode           <- Xcode 支持 (MacOSX 编译)
55```
56
57下面演示Windows10使用Visual Studio2019编译
58
59复制msvc文件夹到一个比较清爽的位置,内部结构如下:
60
61![](API_Doc_Pic/1.jpg)
62
63VS打开capstone.sln项目文件,解决方案自动载入这些
64
65![](API_Doc_Pic/2.jpg)
66
67可以看到支持的所有语言都在这里了,如果都需要的话,直接编译就好了,只需要其中几种,则右键解决方案->属性->配置属性  如下
68
69![](API_Doc_Pic/3.jpg)
70
71生成选项中勾选你需要的支持项即可
72编译后会在当前文件夹Debug目录下生成capstone.lib静态编译库和capstone.dll动态库这样就可以开始使用Capstone进行开发了
73
74如果不想自己编译,官方也提供了官方编译版本
75
76Win32: https://github.com/capstone-engine/capstone/releases/download/4.0.2/capstone-4.0.2-win32.zip
77
78Win64: https://github.com/capstone-engine/capstone/releases/download/4.0.2/capstone-4.0.2-win64.zip
79
80选x32或x64将影响后面开发的位数
81
82
83
84### 引擎调用测试
85
86新建一个VS项目,将capstone\include\capstone中的头文件以及编译好的lib和dll文件全部拷贝到新建项目的主目录下
87
88![](API_Doc_Pic/4.jpg)
89
90在VS解决方案中,头文件添加现有项capstone.h,资源文件中添加capstone.lib,重新生成解决方案
91
92![](API_Doc_Pic/5.jpg)
93
94那么现在来测试一下我们自己的capstone引擎吧
95
96主文件写入如下代码
97
98<details><summary> Code </summary>
99
100```c++
101#include <iostream>
102#include <stdio.h>
103#include <cinttypes>
104#include "capstone.h"
105using namespace std;
106
107#define CODE "\x55\x48\x8b\x05\xb8\x13\x00\x00"
108
109int main(void)
110{
111	csh handle;
112	cs_insn* insn;
113	size_t count;
114
115	if (cs_open(CS_ARCH_X86, CS_MODE_64, &handle)) {
116		printf("ERROR: Failed to initialize engine!\n");
117		return -1;
118	}
119
120	count = cs_disasm(handle, (unsigned char*)CODE, sizeof(CODE) - 1, 0x1000, 0, &insn);
121	if (count) {
122		size_t j;
123
124		for (j = 0; j < count; j++) {
125			printf("0x%""Ix"":\t%s\t\t%s\n", insn[j].address, insn[j].mnemonic, insn[j].op_str);
126		}
127
128		cs_free(insn, count);
129	}
130	else
131		printf("ERROR: Failed to disassemble given code!\n");
132
133	cs_close(&handle);
134
135	return 0;
136}
137```
138
139</details>
140
141运行结果
142![](API_Doc_Pic/6.jpg)
143
144
145
146## 0x1 数据类型
147
148### csh
149
150用于生成调用capstone API的句柄
151
152```cpp
153size_t csh
154```
155
156> 用法: `csh handle;`
157
158
159### cs_arch
160
161架构选择
162
163<details><summary> Code </summary>
164
165```cpp
166 enum cs_arch {
167	CS_ARCH_ARM = 0,	///< ARM 架构 (包括 Thumb, Thumb-2)
168	CS_ARCH_ARM64,		///< ARM-64, 也叫 AArch64
169	CS_ARCH_MIPS,		///< Mips 架构
170   CS_ARCH_X86,		///< X86 架构 (包括 x86 & x86-64)
171	CS_ARCH_PPC,		///< PowerPC 架构
172	CS_ARCH_SPARC,		///< Sparc 架构
173	CS_ARCH_SYSZ,		///< SystemZ 架构
174	CS_ARCH_XCORE,		///< XCore 架构
175	CS_ARCH_M68K,		///< 68K 架构
176	CS_ARCH_TMS320C64X,	///< TMS320C64x 架构
177	CS_ARCH_M680X,		///< 680X 架构
178	CS_ARCH_EVM,		///< Ethereum 架构
179	CS_ARCH_MAX,
180	CS_ARCH_ALL = 0xFFFF, // All 架构 - for cs_support()
181} cs_arch;
182```
183
184</details>
185
186> 用法:API中cs_arch参数填入枚举内容,如API中cs_open(cs_arch arch, cs_mode mode, csh *handle);第一个参数填CS_ARCH_X86则支持X86 架构
187
188
189### cs_mode
190
191模式选择
192
193<details><summary> Code </summary>
194
195```cpp
196enum cs_mode {
197	CS_MODE_LITTLE_ENDIAN = 0,	             ///< little-endian 模式 (default 模式)
198	CS_MODE_ARM = 0,	                     ///< 32-bit ARM
199	CS_MODE_16 = 1 << 1,	                 ///< 16-bit 模式 (X86)
200	CS_MODE_32 = 1 << 2,	                 ///< 32-bit 模式 (X86)
201	CS_MODE_64 = 1 << 3,	                 ///< 64-bit 模式 (X86, PPC)
202	CS_MODE_THUMB = 1 << 4,	                 ///< ARM's Thumb 模式, 包括 Thumb-2
203	CS_MODE_MCLASS = 1 << 5,	             ///< ARM's Cortex-M 系列
204	CS_MODE_V8 = 1 << 6,	                 ///< ARMv8 A32解码方式
205	CS_MODE_MICRO = 1 << 4,                  ///< MicroMips 模式 (MIPS)
206	CS_MODE_MIPS3 = 1 << 5,                  ///< Mips III ISA
207	CS_MODE_MIPS32R6 = 1 << 6,               ///< Mips32r6 ISA
208	CS_MODE_MIPS2 = 1 << 7,                  ///< Mips II ISA
209	CS_MODE_V9 = 1 << 4,                     ///< SparcV9 模式 (Sparc)
210	CS_MODE_QPX = 1 << 4,                    ///< Quad Processing eXtensions 模式 (PPC)
211	CS_MODE_SPE = 1 << 5,                    ///< Signal Processing Engine 模式 (PPC)
212	CS_MODE_BOOKE = 1 << 6,                  ///< Book-E 模式 (PPC)
213	CS_MODE_M68K_000 = 1 << 1,               ///< M68K 68000 模式
214	CS_MODE_M68K_010 = 1 << 2,               ///< M68K 68010 模式
215	CS_MODE_M68K_020 = 1 << 3,               ///< M68K 68020 模式
216	CS_MODE_M68K_030 = 1 << 4,               ///< M68K 68030 模式
217	CS_MODE_M68K_040 = 1 << 5,               ///< M68K 68040 模式
218	CS_MODE_M68K_060 = 1 << 6,               ///< M68K 68060 模式
219	CS_MODE_BIG_ENDIAN = 1 << 31,	         ///< big-endian 模式
220	CS_MODE_MIPS32 = CS_MODE_32,	         ///< Mips32 ISA (Mips)
221	CS_MODE_MIPS64 = CS_MODE_64,	         ///< Mips64 ISA (Mips)
222	CS_MODE_M680X_6301 = 1 << 1,             ///< M680X Hitachi 6301,6303 模式
223	CS_MODE_M680X_6309 = 1 << 2,             ///< M680X Hitachi 6309 模式
224	CS_MODE_M680X_6800 = 1 << 3,             ///< M680X Motorola 6800,6802 模式
225	CS_MODE_M680X_6801 = 1 << 4,             ///< M680X Motorola 6801,6803 模式
226	CS_MODE_M680X_6805 = 1 << 5,             ///< M680X Motorola/Freescale 6805 模式
227	CS_MODE_M680X_6808 = 1 << 6,             ///< M680X Motorola/Freescale/NXP 68HC08 模式
228	CS_MODE_M680X_6809 = 1 << 7,             ///< M680X Motorola 6809 模式
229	CS_MODE_M680X_6811 = 1 << 8,             ///< M680X Motorola/Freescale/NXP 68HC11 模式
230	CS_MODE_M680X_CPU12 = 1 << 9,            ///< M680X Motorola/Freescale/NXP CPU12
231					                         ///< 用于 M68HC12/HCS12
232	CS_MODE_M680X_HCS08 = 1 << 10,           ///< M680X Freescale/NXP HCS08 模式
233	CS_MODE_BPF_CLASSIC = 0,	             ///< Classic BPF 模式 (默认)
234	CS_MODE_BPF_EXTENDED = 1 << 0,	         ///< Extended BPF 模式
235	CS_MODE_RISCV32  = 1 << 0,               ///< RISCV RV32G
236	CS_MODE_RISCV64  = 1 << 1,               ///< RISCV RV64G
237	CS_MODE_RISCVC   = 1 << 2,               ///< RISCV 压缩指令模式
238	CS_MODE_MOS65XX_6502 = 1 << 1,           ///< MOS65XXX MOS 6502
239	CS_MODE_MOS65XX_65C02 = 1 << 2,          ///< MOS65XXX WDC 65c02
240	CS_MODE_MOS65XX_W65C02 = 1 << 3,         ///< MOS65XXX WDC W65c02
241	CS_MODE_MOS65XX_65816 = 1 << 4,          ///< MOS65XXX WDC 65816, 8-bit m/x
242	CS_MODE_MOS65XX_65816_LONG_M = (1 << 5), ///< MOS65XXX WDC 65816, 16-bit m, 8-bit x
243	CS_MODE_MOS65XX_65816_LONG_X = (1 << 6), ///< MOS65XXX WDC 65816, 8-bit m, 16-bit x
244	CS_MODE_MOS65XX_65816_LONG_MX = CS_MODE_MOS65XX_65816_LONG_M | CS_MODE_MOS65XX_65816_LONG_X,
245} cs_mode;
246```
247
248</details>
249
250> 用法:API中cs_mode参数填入枚举内容,如API中cs_open(cs_arch arch, cs_mode mode, csh *handle);第二个参数填CS_MODE_64则支持X64模式
251
252
253### cs_opt_mem
254
255内存操作
256
257<details><summary> Code </summary>
258
259```cpp
260struct cs_opt_mem {
261	cs_malloc_t malloc;
262	cs_calloc_t calloc;
263	cs_realloc_t realloc;
264	cs_free_t free;
265	cs_vsnprintf_t vsnprintf;
266} cs_opt_mem;
267```
268
269</details>
270
271> 用法:可使用用户自定义的malloc/calloc/realloc/free/vsnprintf()函数,默认使用系统自带malloc(), calloc(), realloc(), free() & vsnprintf()
272
273
274### cs_opt_mnem
275
276自定义助记符
277
278<details><summary> Code </summary>
279
280```cpp
281struct cs_opt_mnem {
282	/// 需要自定义的指令ID
283	unsigned int id;
284	/// 自定义的助记符
285	const char *mnemonic;
286} cs_opt_mnem;
287```
288
289</details>
290
291
292### cs_opt_type
293
294反编译的运行时选项
295
296<details><summary> Code </summary>
297
298```cpp
299enum cs_opt_type {
300	CS_OPT_INVALID = 0, 	///< 无特殊要求
301	CS_OPT_SYNTAX,	        ///< 汇编输出语法
302	CS_OPT_DETAIL,	        ///< 将指令结构分解为多个细节
303	CS_OPT_MODE,	        ///< 运行时改变引擎模式
304	CS_OPT_MEM,	            ///< 用户定义的动态内存相关函数
305	CS_OPT_SKIPDATA,        ///< 在反汇编时跳过数据。然后引擎将处于SKIPDATA模式
306	CS_OPT_SKIPDATA_SETUP,  ///< 为SKIPDATA选项设置用户定义函数
307	CS_OPT_MNEMONIC,        ///<自定义指令助记符
308	CS_OPT_UNSIGNED,        ///< 以无符号形式打印立即操作数
309} cs_opt_type;
310```
311
312</details>
313
314> 用法:API cs_option(csh handle, cs_opt_type type, size_t value);中第二个参数
315
316
317### cs_opt_value
318
319运行时选项值(与cs_opt_type关联)
320
321<details><summary> Code </summary>
322
323```cpp
324enum cs_opt_value {
325	CS_OPT_OFF = 0,            ///< 关闭一个选项 - 默认为CS_OPT_DETAIL, CS_OPT_SKIPDATA, CS_OPT_UNSIGNED.
326	CS_OPT_ON = 3,             ///< 打开一个选项 (CS_OPT_DETAIL, CS_OPT_SKIPDATA).
327	CS_OPT_SYNTAX_DEFAULT = 0, ///< 默认asm语法 (CS_OPT_SYNTAX).
328	CS_OPT_SYNTAX_INTEL,       ///< X86 Intel asm语法 - 默认开启 X86 (CS_OPT_SYNTAX).
329	CS_OPT_SYNTAX_ATT,         ///< X86 ATT 汇编语法 (CS_OPT_SYNTAX).
330	CS_OPT_SYNTAX_NOREGNAME,   ///< 只打印寄存器名和编号 (CS_OPT_SYNTAX)
331	CS_OPT_SYNTAX_MASM,        ///< X86 Intel Masm 语法 (CS_OPT_SYNTAX).
332	CS_OPT_SYNTAX_MOTOROLA,    ///< MOS65XX 用 $ 作为hex头
333} cs_opt_value;
334```
335
336</details>
337
338> 用法:API cs_option(csh handle, cs_opt_type type, size_t value);中第三个参数
339
340
341### cs_op_type
342
343通用指令操作数类型,在所有架构中保持一致
344
345<details><summary> Code </summary>
346
347```cpp
348enum cs_op_type {
349	CS_OP_INVALID = 0,  ///< 未初始化/无效的操作数
350	CS_OP_REG,          ///< 寄存器操作数
351	CS_OP_IMM,          ///< 立即操作数
352	CS_OP_MEM,          ///< 内存操作数
353	CS_OP_FP,           ///< 浮点数
354} cs_op_type;
355```
356
357</details>
358
359> 目前开放的API中未调用
360
361
362### cs_ac_type
363
364通用指令操作数访问类型,在所有架构中保持一致
365可以组合访问类型,例如:CS_AC_READ | CS_AC_WRITE
366
367<details><summary> Code </summary>
368
369```cpp
370enum cs_ac_type {
371	CS_AC_INVALID = 0,        ///< 未初始化/无效的访问类型
372	CS_AC_READ    = 1 << 0,   ///< 操作数从内存或寄存器中读取
373	CS_AC_WRITE   = 1 << 1,   ///< 操作数从内存或寄存器中写入
374} cs_ac_type;
375```
376
377</details>
378
379> 目前开放的API中未调用
380
381
382### cs_group_type
383
384公共指令组,在所有架构中保持一致
385
386<details><summary> Code </summary>
387
388```cpp
389cs_group_type {
390	CS_GRP_INVALID = 0,  ///< 未初始化/无效指令组
391	CS_GRP_JUMP,    ///< 所有跳转指令(条件跳转+直接跳转+间接跳转)
392	CS_GRP_CALL,    ///< 所有调用指令
393	CS_GRP_RET,     ///< 所有返回指令
394	CS_GRP_INT,     ///< 所有中断指令(int+syscall)
395	CS_GRP_IRET,    ///< 所有中断返回指令
396	CS_GRP_PRIVILEGE,    ///< 所有特权指令
397	CS_GRP_BRANCH_RELATIVE, ///< 所有相关分支指令
398} cs_group_type;
399```
400
401</details>
402
403> 目前开放的API中未调用
404
405
406### cs_opt_skipdata
407
408用户自定义设置SKIPDATA选项
409
410<details><summary> Code </summary>
411
412```cpp
413struct cs_opt_skipdata {
414	/// Capstone认为要跳过的数据是特殊的“指令”
415	/// 用户可以在这里指定该指令的“助记符”字符串
416	/// 默认情况下(@mnemonic为NULL), Capstone使用“.byte”
417	const char *mnemonic;
418
419	/// 用户定义的回调函数,当Capstone命中数据时调用
420	/// 如果这个回调返回的值是正数(>0),Capstone将跳过这个字节数并继续。如果回调返回0,Capstone将停止反汇编并立即从cs_disasm()返回
421	/// 注意:如果这个回调指针为空,Capstone会根据架构跳过一些字节,如下所示:
422	/// Arm:     2 bytes (Thumb mode) or 4 bytes.
423	/// Arm64:   4 bytes.
424	/// Mips:    4 bytes.
425	/// M680x:   1 byte.
426	/// PowerPC: 4 bytes.
427	/// Sparc:   4 bytes.
428	/// SystemZ: 2 bytes.
429	/// X86:     1 bytes.
430	/// XCore:   2 bytes.
431	/// EVM:     1 bytes.
432	/// RISCV:   4 bytes.
433	/// WASM:    1 bytes.
434	/// MOS65XX: 1 bytes.
435	/// BPF:     8 bytes.
436	cs_skipdata_cb_t callback; 	// 默认值为 NULL
437
438	/// 用户自定义数据将被传递给@callback函数指针
439	void *user_data;
440} cs_opt_skipdata;
441```
442
443</details>
444
445> 目前开放的API中未调用
446
447
448### cs_detail
449
450注意:只有当CS_OPT_DETAIL = CS_OPT_ON时,cs_detail中的所有信息才可用
451
452arch/ARCH/ARCHDisassembler.c的ARCH_getInstruction中初始化为memset(., 0, offsetof(cs_detail, ARCH)+sizeof(cs_ARCH))
453
454如果cs_detail发生了变化,特别是在union之后添加了字段,那么相应地更新arch/ arch/ archdisassembly.c
455
456<details><summary> Code </summary>
457
458```cpp
459struct cs_detail {
460	uint16_t regs_read[16]; ///< 这个参数读取隐式寄存器列表
461	uint8_t regs_read_count; ///< 这个参数读取隐式寄存器计数
462
463	uint16_t regs_write[20]; ///< 这个参数修改隐式寄存器列表
464	uint8_t regs_write_count; ///< 这个参数修改隐式寄存器计数
465
466	uint8_t groups[8]; ///< 此指令所属的指令组的列表
467	uint8_t groups_count; ///< 此指令所属的组的数
468
469	/// 特定于体系结构的信息
470	union {
471		cs_x86 x86;     ///< X86 架构, 包括 16-bit, 32-bit & 64-bit 模式
472		cs_arm64 arm64; ///< ARM64 架构 (aka AArch64)
473		cs_arm arm;     ///< ARM 架构 (包括 Thumb/Thumb2)
474		cs_m68k m68k;   ///< M68K 架构
475		cs_mips mips;   ///< MIPS 架构
476		cs_ppc ppc;	    ///< PowerPC 架构
477		cs_sparc sparc; ///< Sparc 架构
478		cs_sysz sysz;   ///< SystemZ 架构
479		cs_xcore xcore; ///< XCore 架构
480		cs_tms320c64x tms320c64x;  ///< TMS320C64x 架构
481		cs_m680x m680x; ///< M680X 架构
482		cs_evm evm;	    ///< Ethereum 架构
483		cs_mos65xx mos65xx;	///< MOS65XX 架构 (包含 MOS6502)
484		cs_wasm wasm;	///< Web Assembly 架构
485		cs_bpf bpf;	///< Berkeley Packet Filter 架构 (包含 eBPF)
486		cs_riscv riscv; ///< RISCV 架构
487	};
488} cs_detail;
489```
490
491</details>
492
493
494### cs_insn
495
496指令的详细信息
497
498<details><summary> Code </summary>
499
500```cpp
501struct cs_insn {
502	/// 指令ID(基本上是一个用于指令助记符的数字ID)
503	/// 应在相应架构的头文件中查找'[ARCH]_insn' enum中的指令id,如ARM.h中的'arm_insn'代表ARM, X86.h中的'x86_insn'代表X86等…
504	/// 即使在CS_OPT_DETAIL = CS_OPT_OFF时也可以使用此信息
505	/// 注意:在Skipdata模式下,这个id字段的“data”指令为0
506	unsigned int id;
507
508	/// 指令地址 (EIP)
509	/// 即使在CS_OPT_DETAIL = CS_OPT_OFF时也可以使用此信息
510	uint64_t address;
511
512	/// 指令长度
513	/// 即使在CS_OPT_DETAIL = CS_OPT_OFF时也可以使用此信息
514	uint16_t size;
515
516	/// 此指令的机器码,其字节数由上面的@size表示
517	/// 即使在CS_OPT_DETAIL = CS_OPT_OFF时也可以使用此信息
518	uint8_t bytes[24];
519
520	/// 指令的Ascii文本助记符
521	/// 即使在CS_OPT_DETAIL = CS_OPT_OFF时也可以使用此信息
522	char mnemonic[CS_MNEMONIC_SIZE];
523
524	/// 指令操作数的Ascii文本
525	/// 即使在CS_OPT_DETAIL = CS_OPT_OFF时也可以使用此信息
526	char op_str[160];
527
528	/// cs_detail指针
529	/// 注意:只有同时满足以下两个要求时,detail指针才有效:
530	/// (1) CS_OP_DETAIL = CS_OPT_ON
531	/// (2) 引擎未处于Skipdata模式(CS_OP_SKIPDATA选项设置为CS_OPT_ON)
532	///
533	/// 注意2:当处于Skipdata模式或detail模式关闭时,即使这个指针不是NULL,它的内容仍然是不相关的。
534	cs_detail *detail;
535} cs_insn;
536```
537
538</details>
539
540
541### cs_err
542
543Capstone API遇到的各类型的错误时cs_errno()的返回值
544
545<details><summary> Code </summary>
546
547```cpp
548typedef enum cs_err {
549	CS_ERR_OK = 0,    ///< 无错误
550	CS_ERR_MEM,       ///< 内存不足: cs_open(), cs_disasm(), cs_disasm_iter()
551	CS_ERR_ARCH,      ///< 不支持的架构: cs_open()
552	CS_ERR_HANDLE,    ///<句柄不可用: cs_op_count(), cs_op_index()
553	CS_ERR_CSH,       ///< csh参数不可用: cs_close(), cs_errno(), cs_option()
554	CS_ERR_MODE,      ///< 无效的或不支持的模式: cs_open()
555	CS_ERR_OPTION,    ///< 无效的或不支持的选项: cs_option()
556	CS_ERR_DETAIL,    ///< 信息不可用,因为detail选项是关闭的
557	CS_ERR_MEMSETUP,  ///< 动态内存管理未初始化(见 CS_OPT_MEM)
558	CS_ERR_VERSION,   ///< 不支持版本 (bindings)
559	CS_ERR_DIET,      ///< 在“diet”引擎中访问不相关的数据
560	CS_ERR_SKIPDATA,  ///< 在SKIPDATA模式下访问与“数据”指令无关的数据
561	CS_ERR_X86_ATT,   ///< X86 AT&T 语法不支持(在编译时退出)
562	CS_ERR_X86_INTEL, ///< X86 Intel 语法不支持(在编译时退出)
563	CS_ERR_X86_MASM,  ///< X86 Intel 语法不支持(在编译时退出)
564} cs_err;
565```
566
567</details>
568
569
570## 0x2 API
571
572### cs_version
573
574`unsigned int CAPSTONE_API cs_version(int *major, int *minor);`
575
576用来输出capstone版本号
577
578```
579major: API主版本
580minor: API次版本
581return: 返回主次版本的16进制,如4.0版本返回 0x0400
582```
583
584该版本定义于cs.c中,编译后不可更改,不接受自定义版本
585
586![](API_Doc_Pic/7.jpg)
587
588![](API_Doc_Pic/8.jpg)
589
590
591<details><summary> 示例1 </summary>
592
593```c
594#include <stdio.h>
595#include <stdlib.h>
596
597#include "platform.h"
598#include "capstone.h"
599
600static int test()
601{
602	return cs_version(NULL, NULL);
603}
604
605int main()
606{
607	int version = test();
608	printf("%X", version);
609	return 0;
610}
611```
612
613</details>
614
615![](API_Doc_Pic/9.jpg)
616
617
618<details><summary> 示例2,强行修改版本 </summary>
619
620```cpp
621#include <stdio.h>
622#include <stdlib.h>
623
624#include "platform.h"
625#include "capstone.h"
626
627static int test()
628{
629	int ma[] = { 5 };
630	int mi[] = { 6 };
631
632	return cs_version(ma, mi);
633}
634
635int main()
636{
637	int version = test();
638	printf("%X", version);
639	return 0;
640}
641```
642
643</details>
644
645![](API_Doc_Pic/10.jpg)
646
647可见并不能改变
648
649### cs_support
650
651`bool CAPSTONE_API cs_support(int query);`
652
653用来检查capstone库是否支持参数输入的架构或处于某编译选项
654
655<details><summary> 源码实现 </summary>
656
657
658```cpp
659bool CAPSTONE_API cs_support(int query)
660{
661	if (query == CS_ARCH_ALL)
662		return all_arch == ((1 << CS_ARCH_ARM) | (1 << CS_ARCH_ARM64) |
663				(1 << CS_ARCH_MIPS) | (1 << CS_ARCH_X86) |
664				(1 << CS_ARCH_PPC) | (1 << CS_ARCH_SPARC) |
665				(1 << CS_ARCH_SYSZ) | (1 << CS_ARCH_XCORE) |
666				(1 << CS_ARCH_M68K) | (1 << CS_ARCH_TMS320C64X) |
667				(1 << CS_ARCH_M680X) | (1 << CS_ARCH_EVM));
668
669	if ((unsigned int)query < CS_ARCH_MAX)
670		return all_arch & (1 << query);
671
672	if (query == CS_SUPPORT_DIET) {
673#ifdef CAPSTONE_DIET
674		return true;
675#else
676		return false;
677#endif
678	}
679
680	if (query == CS_SUPPORT_X86_REDUCE) {
681#if defined(CAPSTONE_HAS_X86) && defined(CAPSTONE_X86_REDUCE)
682		return true;
683#else
684		return false;
685#endif
686	}
687
688	// unsupported query
689	return false;
690}
691```
692
693</details>
694
695示例1(CS_ARCH_ALL,检查是否支持所有架构)
696
697![](API_Doc_Pic/12.jpg)
698
699示例2(CS_ARCH_*,检查是否支持指定架构)
700
701![](API_Doc_Pic/13.jpg)
702
703示例3(检查是否处于DIET编译模式):
704
705![](API_Doc_Pic/14.jpg)
706
707示例4(检查是否处于X86_REDUCE编译模式)
708
709![](API_Doc_Pic/15.jpg)
710
711
712### cs_malloc_t
713
714`void* (CAPSTONE_API *cs_malloc_t)(size_t size);`
715
716cs的动态内存分配,用于
717
718```cpp
719struct cs_opt_mem {
720	cs_malloc_t malloc;
721	cs_calloc_t calloc;
722	cs_realloc_t realloc;
723	cs_free_t free;
724	cs_vsnprintf_t vsnprintf;
725} cs_opt_mem;
726```
727
728在用户模式下,cs_mem_malloc默认使用系统malloc
729
730Windows driver模式下,`cs_malloc_t cs_mem_malloc = cs_winkernel_malloc;`
731
732cs_winkernel_malloc定义于\capstone-4.0.1\windows\winkernel_mm.c,
733
734<details><summary> 源码实现 </summary>
735
736```cpp
737void * CAPSTONE_API cs_winkernel_malloc(size_t size)
738{
739	// 长度不能分配为0
740	NT_ASSERT(size);
741
742	// FP; NonPagedPool用于支持 Windows 7
743#pragma prefast(suppress : 30030)		// 分配可执行的POOL_TYPE内存
744	size_t number_of_bytes = 0;
745	CS_WINKERNEL_MEMBLOCK *block = NULL;
746	// 特定的值能造成溢出
747	// 如果value中的和超出或低于类型容量,函数将返回NULL。
748	if (!NT_SUCCESS(RtlSizeTAdd(size, sizeof(CS_WINKERNEL_MEMBLOCK), &number_of_bytes))) {
749		return NULL;
750	}
751	block = (CS_WINKERNEL_MEMBLOCK *)ExAllocatePoolWithTag(
752			NonPagedPool, number_of_bytes, CS_WINKERNEL_POOL_TAG);
753	if (!block) {
754		return NULL;
755	}
756	block->size = size;
757
758	return block->data;
759}
760```
761
762</details>
763
764> OSX kernel模式下,`cs_malloc_t cs_mem_malloc = kern_os_malloc;`,这里暂且不探讨。
765
766
767### cs_calloc_t
768
769`void* (CAPSTONE_API *cs_calloc_t)(size_t nmemb, size_t size);`
770
771cs申请内存并初始化
772
773用于`struct cs_opt_mem`,定义于cs.c
774
775用户模式: `cs_calloc_t cs_mem_calloc = calloc;`,使用系统calloc
776
777Windows driver模式: `cs_calloc_t cs_mem_calloc = cs_winkernel_calloc;`
778
779<details><summary> 源码实现 </summary>
780
781```cpp
782void * CAPSTONE_API cs_winkernel_calloc(size_t n, size_t size)
783{
784	size_t total = n * size;
785
786	void *new_ptr = cs_winkernel_malloc(total);
787	if (!new_ptr) {
788		return NULL;
789	}
790
791	return RtlFillMemory(new_ptr, total, 0);
792}
793```
794
795</details>
796
797> OSX kernel模式: `cs_calloc_t cs_mem_calloc = cs_kern_os_calloc;` 直接调用kern_os_malloc
798
799
800### cs_realloc_t
801
802`void* (CAPSTONE_API *cs_realloc_t)(void *ptr, size_t size);`
803
804cs重新分配内存
805
806用于`struct cs_opt_mem`,定义于cs.c
807
808用户模式: `cs_realloc_t cs_mem_realloc = realloc;`,调用系统realloc
809
810Windows driver模式: `cs_realloc_t cs_mem_realloc = cs_winkernel_realloc;`
811
812<details><summary> 源码实现 </summary>
813
814```cpp
815void * CAPSTONE_API cs_winkernel_realloc(void *ptr, size_t size)
816{
817	void *new_ptr = NULL;
818	size_t current_size = 0;
819	size_t smaller_size = 0;
820
821	if (!ptr) {
822		return cs_winkernel_malloc(size);
823	}
824
825	new_ptr = cs_winkernel_malloc(size);
826	if (!new_ptr) {
827		return NULL;
828	}
829
830	current_size = CONTAINING_RECORD(ptr, CS_WINKERNEL_MEMBLOCK, data)->size;
831	smaller_size = (current_size < size) ? current_size : size;
832	RtlCopyMemory(new_ptr, ptr, smaller_size);
833	cs_winkernel_free(ptr);
834
835	return new_ptr;
836}
837```
838
839</details>
840
841> OSX kernel模式: `cs_realloc_t cs_mem_realloc = kern_os_realloc;`
842
843
844### cs_free_t
845
846`typedef void (CAPSTONE_API *cs_free_t)(void *ptr);`
847
848cs释放内存
849
850用于`struct cs_opt_mem`,定义于cs.c
851
852用户模式: `cs_free_t cs_mem_free = free;`,调用系统free
853
854Windows driver模式: `cs_free_t cs_mem_free = cs_winkernel_free;`
855
856<details><summary> 源码实现 </summary>
857
858```cpp
859void CAPSTONE_API cs_winkernel_free(void *ptr)
860{
861	if (ptr) {
862		ExFreePoolWithTag(CONTAINING_RECORD(ptr, CS_WINKERNEL_MEMBLOCK, data), CS_WINKERNEL_POOL_TAG);
863	}
864}
865```
866
867</details>
868
869> OSX kernel模式:  `cs_free_t cs_mem_free = kern_os_free;`
870
871
872
873### cs_vsnprintf_t
874
875`int (CAPSTONE_API *cs_vsnprintf_t)(char *str, size_t size, const char *format, va_list ap);`
876
877按size大小输出到字符串str中
878
879如果系统为wince,将使用_vsnprintf函数
880
881vsnprintf ()和_vsnprintf()对于驱动程序都是可用的,但是它们有一些不同
882
883在需要返回值和设置空终止符时应使用vsnprintf()
884
885Windows driver模式: `cs_vsnprintf_t cs_vsnprintf = cs_winkernel_vsnprintf;`
886
887<details><summary> 源码实现 </summary>
888
889```cpp
890int CAPSTONE_API cs_winkernel_vsnprintf(char *buffer, size_t count, const char *format, va_list argptr)
891{
892	int result = _vsnprintf(buffer, count, format, argptr);
893
894	    // _vsnprintf()在字符串被截断时返回-1,在整个字符串被存储但“buffer”末尾没有“\0”时返回“count”。在这两种情况下,都需要手动添加空终止符。
895	if (result == -1 || (size_t)result == count) {
896		buffer[count - 1] = '\0';
897	}
898
899	if (result == -1) {
900		// 在返回-1时,函数必须获取并返回一些本来要写入的字符。因此,通过重试使用temp buffer进行相同的转换,这个缓冲区就可能足够大来完成格式化,并且获得很多本应写入的字符。
901		char* tmp = cs_winkernel_malloc(0x1000);
902		if (!tmp) {
903			return result;
904		}
905
906		result = _vsnprintf(tmp, 0x1000, format, argptr);
907		NT_ASSERT(result != -1);
908		cs_winkernel_free(tmp);
909	}
910
911	return result;
912}
913```
914
915</details>
916
917> OSX kernel模式: `cs_vsnprintf_t cs_vsnprintf = vsnprintf;`,使用默认vsnprintf
918
919
920
921### cs_skipdata_cb_t
922
923`size_t (CAPSTONE_API *cs_skipdata_cb_t)(const uint8_t *code, size_t code_size, size_t offset, void *user_data);`
924
925SKIPDATA选项的用户自定义回调函数。
926
927```
928code:包含要分解的代码的输入缓冲区。和传递给cs_disasm()的缓冲区相同。
929code_size:上面的code缓冲区的大小(以字节为单位)。
930offset:上面提到的输入缓冲区code中当前检查字节的位置。
931user_data:用户数据通过cs_opt_skipdata结构中的@user_data字段传递给cs_option()。
932return:返回要跳过的字节数,或者0表示立即停止反汇编。
933```
934
935cs_skipdata_cb_t在`struct cs_opt_skipdata`中调用
936
937<details><summary> 示例 </summary>
938
939```cpp
940#include <stdio.h>
941#include <stdlib.h>
942
943#include "platform.h"
944#include "capstone.h"
945
946struct platform {
947	cs_arch arch;
948	cs_mode mode;
949	unsigned char* code;
950	size_t size;
951	const char* comment;
952	cs_opt_type opt_type;
953	cs_opt_value opt_value;
954	cs_opt_type opt_skipdata;
955	size_t skipdata;
956};
957
958static void print_string_hex(unsigned char* str, size_t len)  //输出机器码
959{
960	unsigned char* c;
961
962	printf("Code: ");
963	for (c = str; c < str + len; c++) {
964		printf("0x%02x ", *c & 0xff);
965	}
966	printf("\n");
967}
968
969static void test()
970{
971
972#define X86_CODE32 "\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00\x00\x91\x92"  //测试用机器码
973
974#define RANDOM_CODE "\xed\x00\x00\x00\x00\x1a\x5a\x0f\x1f\xff\xc2\x09\x80\x00\x00\x00\x07\xf7\xeb\x2a\xff\xff\x7f\x57\xe3\x01\xff\xff\x7f\x57\xeb\x00\xf0\x00\x00\x24\xb2\x4f\x00\x78"
975
976	cs_opt_skipdata skipdata = {
977		// 把默认 "data" 描述符从 ".byte" 重命名为 "db"
978		"db",
979	};
980
981	struct platform platforms[2] = {         //以默认描述符和自定义描述符两种方式建立一个数组
982		{
983			CS_ARCH_X86,
984			CS_MODE_32,
985			(unsigned char*)X86_CODE32,
986			sizeof(X86_CODE32) - 1,
987			"X86 32 (Intel syntax) - Skip data",
988		},
989		{
990			CS_ARCH_X86,
991			CS_MODE_32,
992			(unsigned char*)X86_CODE32,
993			sizeof(X86_CODE32) - 1,
994			"X86 32 (Intel syntax) - Skip data with custom mnemonic",
995			CS_OPT_INVALID,
996			CS_OPT_OFF,
997			CS_OPT_SKIPDATA_SETUP,
998			(size_t)& skipdata,
999		},
1000
1001	};
1002
1003	csh handle;   //建立capstone句柄
1004	uint64_t address = 0x1000;  //设置起始地址
1005	cs_insn* insn;  //具体信息结构体
1006	cs_err err;  //错误枚举
1007	int i;
1008	size_t count;  //成功反汇编行数
1009
1010	for (i = 0; i < sizeof(platforms) / sizeof(platforms[0]); i++) {
1011		printf("****************\n");
1012		printf("Platform: %s\n", platforms[i].comment);
1013		err = cs_open(platforms[i].arch, platforms[i].mode, &handle);  //错误检查
1014		if (err) {
1015			printf("Failed on cs_open() with error returned: %u\n", err);
1016			abort();
1017		}
1018
1019		if (platforms[i].opt_type)
1020			cs_option(handle, platforms[i].opt_type, platforms[i].opt_value);
1021
1022		// 打开SKIPDATA 模式
1023		cs_option(handle, CS_OPT_SKIPDATA, CS_OPT_ON);
1024		cs_option(handle, platforms[i].opt_skipdata, platforms[i].skipdata);
1025
1026		count = cs_disasm(handle, platforms[i].code, platforms[i].size, address, 0, &insn);
1027		if (count) {
1028			size_t j;
1029
1030			print_string_hex(platforms[i].code, platforms[i].size);
1031			printf("Disasm:\n");
1032
1033			for (j = 0; j < count; j++) {  //输出汇编
1034				printf("0x%" PRIx64 ":\t%s\t\t%s\n",
1035					insn[j].address, insn[j].mnemonic, insn[j].op_str);
1036			}
1037
1038			// 最后一行代码后打印偏移
1039			printf("0x%" PRIx64 ":\n", insn[j - 1].address + insn[j - 1].size);
1040
1041			// 释放cs_disasm()申请的内存
1042			cs_free(insn, count);
1043		}
1044		else {
1045			printf("****************\n");
1046			printf("Platform: %s\n", platforms[i].comment);
1047			print_string_hex(platforms[i].code, platforms[i].size);
1048			printf("ERROR: Failed to disasm given code!\n");
1049			abort();
1050		}
1051
1052		printf("\n");
1053
1054		cs_close(&handle);
1055	}
1056}
1057
1058int main()
1059{
1060	test();
1061
1062	return 0;
1063}
1064```
1065
1066</details>
1067
1068运行结果如下,默认的.byte数据类型被改为db描述符
1069
1070![](API_Doc_Pic/11.jpg)
1071
1072
1073
1074
1075### cs_open
1076
1077`cs_err CAPSTONE_API cs_open(cs_arch arch, cs_mode mode, csh *handle);`
1078
1079初始化cs句柄
1080
1081```
1082arch: 架构类型 (CS_ARCH_*)
1083mode: 硬件模式. CS_MODE_*在cs_mode数据类型中可查
1084handle: 指向句柄, 返回时更新
1085return: 创建成功返回CS_ERR_OK,否则返回cs_err枚举中对应的错误信息
1086```
1087
1088<details><summary> 源码实现 </summary>
1089
1090```cpp
1091cs_err CAPSTONE_API cs_open(cs_arch arch, cs_mode mode, csh *handle)
1092{
1093	cs_err err;
1094	struct cs_struct *ud;
1095	if (!cs_mem_malloc || !cs_mem_calloc || !cs_mem_realloc || !cs_mem_free || !cs_vsnprintf)
1096		// Error: 使用cs_open()前, 必须使用cs_option(CS_OPT_MEM)进行动态内存管理的初始化
1097		return CS_ERR_MEMSETUP;
1098
1099	if (arch < CS_ARCH_MAX && cs_arch_init[arch]) {
1100		// 验证架构是否使用,方式:架构在枚举中且可初始化
1101		if (mode & cs_arch_disallowed_mode_mask[arch]) {
1102			*handle = 0;
1103			return CS_ERR_MODE;
1104		}
1105
1106		ud = cs_mem_calloc(1, sizeof(*ud));
1107		if (!ud) {
1108			// 内存不足
1109			return CS_ERR_MEM;
1110		}
1111
1112		ud->errnum = CS_ERR_OK;
1113		ud->arch = arch;
1114		ud->mode = mode;
1115		// 默认情况指令不打开detail模式
1116		ud->detail = CS_OPT_OFF;
1117
1118		// 默认skipdata设置
1119		ud->skipdata_setup.mnemonic = SKIPDATA_MNEM;
1120
1121		err = cs_arch_init[ud->arch](ud);
1122		if (err) {
1123			cs_mem_free(ud);
1124			*handle = 0;
1125			return err;
1126		}
1127
1128		*handle = (uintptr_t)ud;
1129
1130		return CS_ERR_OK;
1131	} else {
1132		*handle = 0;
1133		return CS_ERR_ARCH;
1134	}
1135}
1136```
1137
1138其中,cs_struct结构体包含更多细节设定,如下
1139
1140```cpp
1141struct cs_struct {
1142	cs_arch arch;
1143	cs_mode mode;
1144	Printer_t printer;	// 打印asm
1145	void *printer_info; // 打印信息
1146	Disasm_t disasm;	// 反编译
1147	void *getinsn_info; // 打印辅助信息
1148	GetName_t reg_name;
1149	GetName_t insn_name;
1150	GetName_t group_name;
1151	GetID_t insn_id;
1152	PostPrinter_t post_printer;
1153	cs_err errnum;
1154	ARM_ITStatus ITBlock;	// ARM特殊选项
1155	cs_opt_value detail, imm_unsigned;
1156	int syntax;	//ARM, Mips & PPC等架构的基本asm语法打印
1157	bool doing_mem;	// 在InstPrinter代码中处理内存操作数
1158	unsigned short *insn_cache;	//为mapping.c建立缓存索引
1159	GetRegisterName_t get_regname;
1160	bool skipdata;	// 如果反编译时要跳过数据,该项设置为True
1161	uint8_t skipdata_size;	//要跳过bytes的数量
1162	cs_opt_skipdata skipdata_setup;	// 自定义skipdata设置
1163	const uint8_t *regsize_map;	//映射register大小 (目前仅支持x86)
1164	GetRegisterAccess_t reg_access;
1165	struct insn_mnem *mnem_list;	// 自定义指令助记符的链接list
1166};
1167```
1168
1169</details>
1170
1171示例(创建一个x86_64类型的cs句柄)
1172
1173`cs_open(CS_ARCH_X86, CS_MODE_64, &handle)`
1174
1175
1176### cs_close
1177
1178`cs_err CAPSTONE_API cs_close(csh *handle);`
1179
1180释放句柄
1181
1182```
1183handle: 指向一个cs_open()打开的句柄
1184return: 释放成功返回CS_ERR_OK,否则返回cs_err枚举的错误信息
1185```
1186
1187释放句柄实质为将句柄值设置为0
1188
1189<details><summary> 源码实现 </summary>
1190
1191```cpp
1192cs_err CAPSTONE_API cs_close(csh *handle)
1193{
1194	struct cs_struct *ud;
1195	struct insn_mnem *next, *tmp;
1196
1197	if (*handle == 0)
1198		// 句柄不可用
1199		return CS_ERR_CSH;
1200
1201	ud = (struct cs_struct *)(*handle);
1202
1203	if (ud->printer_info)
1204		cs_mem_free(ud->printer_info);
1205
1206	// 释放自定义助记符的链接list
1207	tmp = ud->mnem_list;
1208	while(tmp) {
1209		next = tmp->next;
1210		cs_mem_free(tmp);
1211		tmp = next;
1212	}
1213
1214	cs_mem_free(ud->insn_cache);
1215
1216	memset(ud, 0, sizeof(*ud));
1217	cs_mem_free(ud);
1218
1219	// handle值设置为0,保证这个句柄在cs_close()释放后不可使用
1220	*handle = 0;
1221
1222	return CS_ERR_OK;
1223}
1224```
1225
1226</details>
1227
1228示例
1229
1230`cs_close(&handle);`
1231
1232
1233### cs_option
1234
1235`cs_err CAPSTONE_API cs_option(csh handle, cs_opt_type type, size_t value);`
1236
1237反编译引擎的运行时选项
1238
1239```
1240handle: cs_open()打开的句柄
1241type: 设置选项的类型
1242value: 与type对应的选项值
1243return: 设置成功返回CS_ERR_OK,否则返回cs_err枚举的错误信息
1244```
1245
1246注意: 在CS_OPT_MEM的情况下,handle可以是任何值,因此cs_option(handle, CS_OPT_MEM, value)必须在cs_open()之前被调用
1247
1248<details><summary> 源码实现 </summary>
1249
1250```cpp
1251cs_err CAPSTONE_API cs_option(csh ud, cs_opt_type type, size_t value)
1252{
1253	struct cs_struct *handle;
1254	cs_opt_mnem *opt;
1255
1256	// 支持在所有API前支持 (even cs_open())
1257	if (type == CS_OPT_MEM) {
1258		cs_opt_mem *mem = (cs_opt_mem *)value;
1259
1260		cs_mem_malloc = mem->malloc;
1261		cs_mem_calloc = mem->calloc;
1262		cs_mem_realloc = mem->realloc;
1263		cs_mem_free = mem->free;
1264		cs_vsnprintf = mem->vsnprintf;
1265
1266		return CS_ERR_OK;
1267	}
1268
1269	handle = (struct cs_struct *)(uintptr_t)ud;
1270	if (!handle)
1271		return CS_ERR_CSH;
1272
1273	switch(type) {
1274		default:
1275			break;
1276
1277		case CS_OPT_UNSIGNED:
1278			handle->imm_unsigned = (cs_opt_value)value;
1279			return CS_ERR_OK;
1280
1281		case CS_OPT_DETAIL:
1282			handle->detail = (cs_opt_value)value;
1283			return CS_ERR_OK;
1284
1285		case CS_OPT_SKIPDATA:
1286			handle->skipdata = (value == CS_OPT_ON);
1287			if (handle->skipdata) {
1288				if (handle->skipdata_size == 0) {
1289					handle->skipdata_size = skipdata_size(handle);
1290				}
1291			}
1292			return CS_ERR_OK;
1293
1294		case CS_OPT_SKIPDATA_SETUP:
1295			if (value)
1296				handle->skipdata_setup = *((cs_opt_skipdata *)value);
1297			return CS_ERR_OK;
1298
1299		case CS_OPT_MNEMONIC:
1300			opt = (cs_opt_mnem *)value;
1301			if (opt->id) {
1302				if (opt->mnemonic) {
1303					struct insn_mnem *tmp;
1304
1305					// 添加新指令或替换现有指令
1306					// 查看当前insn释放在list中
1307					tmp = handle->mnem_list;
1308					while(tmp) {
1309						if (tmp->insn.id == opt->id) {
1310							// f找到指令,替换助记符
1311							(void)strncpy(tmp->insn.mnemonic, opt->mnemonic, sizeof(tmp->insn.mnemonic) - 1);
1312							tmp->insn.mnemonic[sizeof(tmp->insn.mnemonic) - 1] = '\0';
1313							break;
1314						}
1315						tmp = tmp->next;
1316					}
1317
1318					// 2. 如果没有就添加这条指令
1319					if (!tmp) {
1320						tmp = cs_mem_malloc(sizeof(*tmp));
1321						tmp->insn.id = opt->id;
1322						(void)strncpy(tmp->insn.mnemonic, opt->mnemonic, sizeof(tmp->insn.mnemonic) - 1);
1323						tmp->insn.mnemonic[sizeof(tmp->insn.mnemonic) - 1] = '\0';
1324						// 新指令放在list最前面
1325						tmp->next = handle->mnem_list;
1326						handle->mnem_list = tmp;
1327					}
1328					return CS_ERR_OK;
1329				} else {
1330					struct insn_mnem *prev, *tmp;
1331
1332					tmp = handle->mnem_list;
1333					prev = tmp;
1334					while(tmp) {
1335						if (tmp->insn.id == opt->id) {
1336							// 删除指令
1337							if (tmp == prev) {
1338								handle->mnem_list = tmp->next;
1339							} else {
1340								prev->next = tmp->next;
1341							}
1342							cs_mem_free(tmp);
1343							break;
1344						}
1345						prev = tmp;
1346						tmp = tmp->next;
1347					}
1348				}
1349			}
1350			return CS_ERR_OK;
1351
1352		case CS_OPT_MODE:
1353			// 验证所请求的模式是否有效
1354			if (value & cs_arch_disallowed_mode_mask[handle->arch]) {
1355				return CS_ERR_OPTION;
1356			}
1357			break;
1358	}
1359
1360	return cs_arch_option[handle->arch](handle, type, value);
1361}
1362```
1363</details>
1364
1365
1366<details><summary> 示例,更改反汇编后显示的语法 </summary>
1367
1368```cpp
1369#include <iostream>
1370#include <stdio.h>
1371
1372#include "capstone.h"
1373#include "platform.h"
1374
1375using namespace std;
1376
1377#define CODE "\x55\x48\x8b\x05\xb8\x13\x00\x00"
1378
1379int main(void)
1380{
1381	csh handle;
1382	cs_insn* insn;
1383	size_t count;
1384
1385	if (cs_open(CS_ARCH_X86, CS_MODE_64, &handle)) {
1386		printf("ERROR: Failed to initialize engine!\n");
1387		return -1;
1388	}
1389	cs_option(handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT);  // 以AT&T语法显示
1390	count = cs_disasm(handle, (unsigned char*)CODE, sizeof(CODE) - 1, 0x1000, 0, &insn);
1391	if (count) {
1392		size_t j;
1393
1394		for (j = 0; j < count; j++) {
1395			printf("0x%""Ix"":\t%s\t\t%s\n", insn[j].address, insn[j].mnemonic, insn[j].op_str);
1396		}
1397
1398		cs_free(insn, count);
1399	}
1400	else
1401		printf("ERROR: Failed to disassemble given code!\n");
1402
1403	cs_close(&handle);
1404
1405	return 0;
1406}
1407```
1408
1409</details>
1410
1411输出
1412
1413![](API_Doc_Pic/16.jpg)
1414
1415
1416### cs_errno
1417
1418`cs_err CAPSTONE_API cs_errno(csh handle);`
1419
1420API出错时返回错误消息
1421
1422```
1423handle: cs_open()打开的句柄
1424return: 无错误返回CS_ERR_OK,否则返回cs_err枚举的错误信息
1425```
1426
1427判断到句柄不存在直接返回CS_ERR_CSH
1428
1429<details><summary> 示例 </summary>
1430
1431```cpp
1432#include <iostream>
1433#include <stdio.h>
1434
1435#include "capstone.h"
1436#include "platform.h"
1437
1438using namespace std;
1439
1440#define CODE "\x55\x48\x8b\x05\xb8\x13\x00\x00"
1441
1442int main(void)
1443{
1444	csh handle = 0;
1445	cs_insn* insn;
1446	size_t count;
1447
1448	if (cs_open(CS_ARCH_X86, CS_MODE_64, &handle)) {
1449		printf("ERROR: Failed to initialize engine!\n");
1450		return -1;
1451	}
1452
1453	cs_close(&handle);
1454	std::cout << cs_errno(handle);    //关闭句柄后检查将报错
1455	return 0;
1456}
1457```
1458
1459</details>
1460
1461输出,错误码4即CS_ERR_CSH
1462
1463![](API_Doc_Pic/17.jpg)
1464
1465
1466### cs_strerror
1467
1468`const char * CAPSTONE_API cs_strerror(cs_err code);`
1469
1470将上个API输出的错误码转换为详细错误信息
1471
1472<details><summary> 源码实现 </summary>
1473
1474```cpp
1475const char * CAPSTONE_API cs_strerror(cs_err code)
1476{
1477	switch(code) {
1478		default:
1479			return "Unknown error code";
1480		case CS_ERR_OK:
1481			return "OK (CS_ERR_OK)";
1482		case CS_ERR_MEM:
1483			return "Out of memory (CS_ERR_MEM)";
1484		case CS_ERR_ARCH:
1485			return "Invalid/unsupported architecture(CS_ERR_ARCH)";
1486		case CS_ERR_HANDLE:
1487			return "Invalid handle (CS_ERR_HANDLE)";
1488		case CS_ERR_CSH:
1489			return "Invalid csh (CS_ERR_CSH)";
1490		case CS_ERR_MODE:
1491			return "Invalid mode (CS_ERR_MODE)";
1492		case CS_ERR_OPTION:
1493			return "Invalid option (CS_ERR_OPTION)";
1494		case CS_ERR_DETAIL:
1495			return "Details are unavailable (CS_ERR_DETAIL)";
1496		case CS_ERR_MEMSETUP:
1497			return "Dynamic memory management uninitialized (CS_ERR_MEMSETUP)";
1498		case CS_ERR_VERSION:
1499			return "Different API version between core & binding (CS_ERR_VERSION)";
1500		case CS_ERR_DIET:
1501			return "Information irrelevant in diet engine (CS_ERR_DIET)";
1502		case CS_ERR_SKIPDATA:
1503			return "Information irrelevant for 'data' instruction in SKIPDATA mode (CS_ERR_SKIPDATA)";
1504		case CS_ERR_X86_ATT:
1505			return "AT&T syntax is unavailable (CS_ERR_X86_ATT)";
1506		case CS_ERR_X86_INTEL:
1507			return "INTEL syntax is unavailable (CS_ERR_X86_INTEL)";
1508		case CS_ERR_X86_MASM:
1509			return "MASM syntax is unavailable (CS_ERR_X86_MASM)";
1510	}
1511}
1512```
1513</details>
1514
1515
1516<details><summary> 示例,结合cs_errno使用 </summary>
1517
1518```cpp
1519#include <iostream>
1520#include <stdio.h>
1521
1522#include "capstone.h"
1523#include "platform.h"
1524
1525using namespace std;
1526
1527#define CODE "\x55\x48\x8b\x05\xb8\x13\x00\x00"
1528
1529int main(void)
1530{
1531	csh handle = 0;
1532	cs_insn* insn;
1533	size_t count;
1534
1535	if (cs_open(CS_ARCH_X86, CS_MODE_64, &handle)) {
1536		printf("ERROR: Failed to initialize engine!\n");
1537		return -1;
1538	}
1539
1540	cs_close(&handle);
1541	std::cout << cs_strerror(cs_errno(handle));  //直接输出报错信息
1542	return 0;
1543}
1544```
1545
1546</details>
1547
1548输出
1549
1550![](API_Doc_Pic/18.jpg)
1551
1552
1553### cs_disasm
1554
1555```cpp
1556size_t CAPSTONE_API cs_disasm(csh handle,
1557		const uint8_t *code, size_t code_size,
1558		uint64_t address,
1559		size_t count,
1560		cs_insn **insn);
1561```
1562
1563给定缓冲区、大小、地址和编号,反编译机器码
1564
1565API动态地分配内存来包含分解的指令,生成的指令将放在*insn中
1566
1567注意: 必须释放分配的内存,以避免内存泄漏。对于需要动态分配稀缺内存的系统(如OS内核或固件),API cs_disasm_iter()可能是比cs_disasm()更好的选择。原因是,使用cs_disasm()时,基于有限的可用内存,必须预先计算要分解多少条指令。
1568
1569```
1570handle: cs_open()返回的句柄
1571code: 包含要反汇编的机器码的缓冲区。
1572code_size:上面代码缓冲区的大小。
1573address:给定原始代码缓冲区中的第一条指令的地址。
1574insn: 由这个API填写的指令数组。注意: insn将由这个函数分配,应该用cs_free () API释放
1575count: 需要分解的指令数量,或输入0分解所有指令
1576return:成功反汇编指令的数量,如果该函数未能反汇编给定的代码,则为0,失败时,调用cs_errno()获取错误代码。
1577```
1578
1579<details><summary> 源码实现 </summary>
1580
1581```cpp
1582size_t CAPSTONE_API cs_disasm(csh ud, const uint8_t *buffer, size_t size, uint64_t offset, size_t count, cs_insn **insn)
1583{
1584	struct cs_struct *handle;
1585	MCInst mci;
1586	uint16_t insn_size;
1587	size_t c = 0, i;
1588	unsigned int f = 0;	// 缓存中下一条指令的索引
1589	cs_insn *insn_cache;	// 缓存反汇编后的指令
1590	void *total = NULL;
1591	size_t total_size = 0;	//所有insn的输出缓冲区的总大小
1592	bool r;
1593	void *tmp;
1594	size_t skipdata_bytes;
1595	uint64_t offset_org; // 保存缓冲区的所有原始信息
1596	size_t size_org;
1597	const uint8_t *buffer_org;
1598	unsigned int cache_size = INSN_CACHE_SIZE;
1599	size_t next_offset;
1600
1601	handle = (struct cs_struct *)(uintptr_t)ud;
1602	if (!handle) {
1603		// 修复方式:
1604		// handle->errnum = CS_ERR_HANDLE;
1605		return 0;
1606	}
1607
1608	handle->errnum = CS_ERR_OK;
1609
1610	// 重设ARM架构的IT block
1611	if (handle->arch == CS_ARCH_ARM)
1612		handle->ITBlock.size = 0;
1613
1614#ifdef CAPSTONE_USE_SYS_DYN_MEM
1615	if (count > 0 && count <= INSN_CACHE_SIZE)
1616		cache_size = (unsigned int) count;
1617#endif
1618
1619	// 保存SKIPDATA原始偏移量
1620	buffer_org = buffer;
1621	offset_org = offset;
1622	size_org = size;
1623
1624	total_size = sizeof(cs_insn) * cache_size;
1625	total = cs_mem_malloc(total_size);
1626	if (total == NULL) {
1627		// 内存不足
1628		handle->errnum = CS_ERR_MEM;
1629		return 0;
1630	}
1631
1632	insn_cache = total;
1633
1634	while (size > 0) {
1635		MCInst_Init(&mci);
1636		mci.csh = handle;
1637
1638		mci.address = offset;
1639
1640		if (handle->detail) {
1641			//给detail指针分配内存
1642			insn_cache->detail = cs_mem_malloc(sizeof(cs_detail));
1643		} else {
1644			insn_cache->detail = NULL;
1645		}
1646
1647		// 为non-detailed模式保存所有信息
1648		mci.flat_insn = insn_cache;
1649		mci.flat_insn->address = offset;
1650#ifdef CAPSTONE_DIET
1651		//mnemonic & op_str0填充
1652		mci.flat_insn->mnemonic[0] = '\0';
1653		mci.flat_insn->op_str[0] = '\0';
1654#endif
1655
1656		r = handle->disasm(ud, buffer, size, &mci, &insn_size, offset, handle->getinsn_info);
1657		if (r) {
1658			SStream ss;
1659			SStream_Init(&ss);
1660
1661			mci.flat_insn->size = insn_size;
1662
1663			//将内部指令操作码映射到公共insn ID
1664			handle->insn_id(handle, insn_cache, mci.Opcode);
1665
1666			handle->printer(&mci, &ss, handle->printer_info);
1667			fill_insn(handle, insn_cache, ss.buffer, &mci, handle->post_printer, buffer);
1668
1669			// 调整opcode (X86)
1670			if (handle->arch == CS_ARCH_X86)
1671				insn_cache->id += mci.popcode_adjust;
1672
1673			next_offset = insn_size;
1674		} else	{
1675			// 遇到中断指令
1676
1677			// 为detail指针释放内存
1678			if (handle->detail) {
1679				cs_mem_free(insn_cache->detail);
1680			}
1681
1682			if (!handle->skipdata || handle->skipdata_size > size)
1683				break;
1684
1685			if (handle->skipdata_setup.callback) {
1686				skipdata_bytes = handle->skipdata_setup.callback(buffer_org, size_org,
1687						(size_t)(offset - offset_org), handle->skipdata_setup.user_data);
1688				if (skipdata_bytes > size)
1689					break;
1690
1691				if (!skipdata_bytes)
1692					break;
1693			} else
1694				skipdata_bytes = handle->skipdata_size;
1695
1696			insn_cache->id = 0;
1697			insn_cache->address = offset;
1698			insn_cache->size = (uint16_t)skipdata_bytes;
1699			memcpy(insn_cache->bytes, buffer, skipdata_bytes);
1700#ifdef CAPSTONE_DIET
1701			insn_cache->mnemonic[0] = '\0';
1702			insn_cache->op_str[0] = '\0';
1703#else
1704			strncpy(insn_cache->mnemonic, handle->skipdata_setup.mnemonic,
1705					sizeof(insn_cache->mnemonic) - 1);
1706			skipdata_opstr(insn_cache->op_str, buffer, skipdata_bytes);
1707#endif
1708			insn_cache->detail = NULL;
1709
1710			next_offset = skipdata_bytes;
1711		}
1712
1713		// 一条新指令进入缓存
1714		f++;
1715
1716		// 反汇编了一条指令
1717		c++;
1718		if (count > 0 && c == count)
1719			break;
1720
1721		if (f == cache_size) {
1722			cache_size = cache_size * 8 / 5;
1723			total_size += (sizeof(cs_insn) * cache_size);
1724			tmp = cs_mem_realloc(total, total_size);
1725			if (tmp == NULL) {	//内存不足
1726				if (handle->detail) {
1727					insn_cache = (cs_insn *)total;
1728					for (i = 0; i < c; i++, insn_cache++)
1729						cs_mem_free(insn_cache->detail);
1730				}
1731
1732				cs_mem_free(total);
1733				*insn = NULL;
1734				handle->errnum = CS_ERR_MEM;
1735				return 0;
1736			}
1737
1738			total = tmp;
1739			//在最后一条指令之后继续填充缓存
1740			insn_cache = (cs_insn *)((char *)total + sizeof(cs_insn) * c);
1741
1742			// 将f重置为0,从一开始就填入缓存
1743			f = 0;
1744		} else
1745			insn_cache++;
1746
1747		buffer += next_offset;
1748		size -= next_offset;
1749		offset += next_offset;
1750	}
1751
1752	if (!c) {
1753		//未反汇编任何指令
1754		cs_mem_free(total);
1755		total = NULL;
1756	} else if (f != cache_size) {
1757		// 没有完全使用最后一个缓存,缩小大小
1758		tmp = cs_mem_realloc(total, total_size - (cache_size - f) * sizeof(*insn_cache));
1759		if (tmp == NULL) {	// 内存不足
1760			// 释放所有detail指针
1761			if (handle->detail) {
1762				insn_cache = (cs_insn *)total;
1763				for (i = 0; i < c; i++, insn_cache++)
1764					cs_mem_free(insn_cache->detail);
1765			}
1766
1767			cs_mem_free(total);
1768			*insn = NULL;
1769
1770			handle->errnum = CS_ERR_MEM;
1771			return 0;
1772		}
1773
1774		total = tmp;
1775	}
1776
1777	*insn = total;
1778
1779	return c;
1780}
1781```
1782
1783</details>
1784
1785
1786<details><summary> 示例,x86_64 </summary>
1787
1788```cpp
1789#include <iostream>
1790#include <stdio.h>
1791
1792#include "capstone.h"
1793#include "platform.h"
1794
1795using namespace std;
1796
1797#define CODE "\x55\x48\x8b\x05\xb8\x13\x00\x00\xe9\xea\xbe\xad\xde\xff\x25\x23\x01\x00\x00\xe8\xdf\xbe\xad\xde\x74\xff"
1798
1799int main(void)
1800{
1801	csh handle = 0;
1802	cs_insn* insn;
1803	size_t count;
1804
1805	if (cs_open(CS_ARCH_X86, CS_MODE_64, &handle)) {
1806		printf("ERROR: Failed to initialize engine!\n");
1807		return -1;
1808	}
1809
1810	count = cs_disasm(handle, (unsigned char*)CODE, sizeof(CODE) - 1, 0x1000, 0, &insn);   //所有指令,基址0x1000,放入insn
1811	if (count) {
1812		size_t j;
1813
1814		for (j = 0; j < count; j++) {
1815			printf("0x%""Ix"":\t%s\t\t%s\n", insn[j].address, insn[j].mnemonic, insn[j].op_str);
1816		}
1817
1818		cs_free(insn, count);
1819	}
1820	else
1821		printf("ERROR: Failed to disassemble given code!\n");
1822
1823	cs_close(&handle);
1824
1825	return 0;
1826}
1827```
1828
1829</details>
1830
1831输出
1832
1833![](API_Doc_Pic/19.jpg)
1834
1835
1836### cs_free
1837
1838`void CAPSTONE_API cs_free(cs_insn *insn, size_t count);`
1839
1840释放被 cs_malloc() 或 cs_disasm() 分配的内存(insn参数)
1841
1842```
1843insn: 由cs_disasm()或cs_malloc()中的@insn参数返回的指针
1844count: 赋值由cs_disasm()返回的cs_insn结构的数量,或赋值为1表示由cs_malloc()分配给空闲内存的数量
1845```
1846
1847<details><summary> 源码实现 </summary>
1848
1849```cpp
1850void CAPSTONE_API cs_free(cs_insn *insn, size_t count)
1851{
1852	size_t i;
1853
1854	// free 所有 detail 指针
1855	for (i = 0; i < count; i++)
1856		cs_mem_free(insn[i].detail);
1857
1858	cs_mem_free(insn);
1859}
1860```
1861
1862直接调用cs_mem_free,也就是默认的free
1863
1864</details>
1865
1866
1867<details><summary> 示例(释放cs_disasm申请的内存) </summary>
1868
1869```cpp
1870	count = cs_disasm(handle, (unsigned char*)CODE, sizeof(CODE) - 1, 0x1000, 0, &insn);           //计数由cs_disasm申请的内存
1871	if (count) {
1872		size_t j;
1873
1874		for (j = 0; j < count; j++) {
1875			printf("0x%""Ix"":\t%s\t\t%s\n", insn[j].address, insn[j].mnemonic, insn[j].op_str);
1876		}
1877
1878		cs_free(insn, count);   //循环依次释放每条insn的内存
1879	}
1880```
1881
1882</details>
1883
1884
1885### cs_malloc
1886
1887`cs_insn * CAPSTONE_API cs_malloc(csh handle);`
1888
1889被用于在API cs_disasm_iter()中为一条指令分配内存
1890
1891```
1892handle: cs_open()返回的句柄
1893```
1894
1895<details><summary> 源码实现 </summary>
1896
1897```cpp
1898cs_insn * CAPSTONE_API cs_malloc(csh ud)
1899{
1900	cs_insn *insn;
1901	struct cs_struct *handle = (struct cs_struct *)(uintptr_t)ud;
1902
1903	insn = cs_mem_malloc(sizeof(cs_insn));
1904	if (!insn) {
1905		// insufficient memory
1906		handle->errnum = CS_ERR_MEM;
1907		return NULL;
1908	} else {
1909		if (handle->detail) {
1910			// allocate memory for @detail pointer
1911			insn->detail = cs_mem_malloc(sizeof(cs_detail));
1912			if (insn->detail == NULL) {	// insufficient memory
1913				cs_mem_free(insn);
1914				handle->errnum = CS_ERR_MEM;
1915				return NULL;
1916			}
1917		} else
1918			insn->detail = NULL;
1919	}
1920
1921	return insn;
1922}
1923```
1924
1925</details>
1926
1927当这条指令所占的内存不再使用时,使用cs_free(insn, 1)释放,示例在下面cs_disasm_iter处
1928
1929
1930### cs_disasm_iter
1931
1932```cpp
1933bool CAPSTONE_API cs_disasm_iter(csh handle,
1934	const uint8_t **code, size_t *size,
1935	uint64_t *address, cs_insn *insn);
1936```
1937
1938给定buff、大小、地址和要解码的指令数,更快速的反汇编机器码,
1939这个API将生成的指令放入insn中的给定的缓存中。
1940
1941注意1: 此API将更新code、size和address以指向输入缓冲区中的下一条指令。所以,虽然每次反汇编一条指令可以使用cs_disasm(count=1)来实现,但一些基准测试显示,在循环中使用cs_disasm_iter()可以方便地快速迭代所有指令,在随机输入时可以快30%。
1942
1943注意2:可以使用cs_malloc()创建insn中的缓存。
1944
1945注意3:对于动态分配内存可能产生内存不足的系统(比如OS内核或固件),建议使用cs_disasm()这个API, 因为cs_disasm()是根据要分解的指令的数量来分配内存。
1946
1947```
1948handle: cs_open()返回的句柄
1949code: 要反汇编的机器码所在的缓冲区
1950size: 机器码缓冲区的大小
1951address: 所给机器码缓冲区中第一个insn的地址
1952insn: 指向这个API要填充的指令的指针。
1953return:如果这个API成功反汇编了一条指令返回true,否则将返回false。
1954```
1955
1956失败时,调用cs_errno()获取错误代码。
1957
1958<details><summary> 代码实现,在cs_disasm基础上使用动态内存分配 </summary>
1959
1960```cpp
1961bool CAPSTONE_API cs_disasm_iter(csh ud, const uint8_t **code, size_t *size,
1962		uint64_t *address, cs_insn *insn)
1963{
1964	struct cs_struct *handle;
1965	uint16_t insn_size;
1966	MCInst mci;
1967	bool r;
1968
1969	handle = (struct cs_struct *)(uintptr_t)ud;
1970	if (!handle) {
1971		return false;
1972	}
1973
1974	handle->errnum = CS_ERR_OK;
1975
1976	MCInst_Init(&mci);
1977	mci.csh = handle;
1978
1979	mci.address = *address;
1980
1981	// 为无detail模式保存相关信息
1982	mci.flat_insn = insn;
1983	mci.flat_insn->address = *address;
1984#ifdef CAPSTONE_DIET
1985	mci.flat_insn->mnemonic[0] = '\0';
1986	mci.flat_insn->op_str[0] = '\0';
1987#endif
1988
1989	r = handle->disasm(ud, *code, *size, &mci, &insn_size, *address, handle->getinsn_info);
1990	if (r) {
1991		SStream ss;
1992		SStream_Init(&ss);
1993
1994		mci.flat_insn->size = insn_size;
1995
1996		// 将内部指令操作码映射到公共insn ID
1997		handle->insn_id(handle, insn, mci.Opcode);
1998
1999		handle->printer(&mci, &ss, handle->printer_info);
2000
2001		fill_insn(handle, insn, ss.buffer, &mci, handle->post_printer, *code);
2002
2003		// 调整伪操作码(X86)
2004		if (handle->arch == CS_ARCH_X86)
2005			insn->id += mci.popcode_adjust;
2006
2007		*code += insn_size;
2008		*size -= insn_size;
2009		*address += insn_size;
2010	} else { 	// 遇到中断指令
2011		size_t skipdata_bytes;
2012
2013		// 如果没有跳过数据的请求,或者剩余数据太小,则退出
2014		if (!handle->skipdata || handle->skipdata_size > *size)
2015			return false;
2016
2017		if (handle->skipdata_setup.callback) {
2018			skipdata_bytes = handle->skipdata_setup.callback(*code, *size,
2019					0, handle->skipdata_setup.user_data);
2020			if (skipdata_bytes > *size)
2021				// 剩余数据太小
2022				return false;
2023
2024			if (!skipdata_bytes)
2025				return false;
2026		} else
2027			skipdata_bytes = handle->skipdata_size;
2028
2029		// 基于架构和模式跳过一些数据
2030		insn->id = 0;	// 此“数据”指令的ID无效
2031		insn->address = *address;
2032		insn->size = (uint16_t)skipdata_bytes;
2033#ifdef CAPSTONE_DIET
2034		insn->mnemonic[0] = '\0';
2035		insn->op_str[0] = '\0';
2036#else
2037		memcpy(insn->bytes, *code, skipdata_bytes);
2038		strncpy(insn->mnemonic, handle->skipdata_setup.mnemonic,
2039				sizeof(insn->mnemonic) - 1);
2040		skipdata_opstr(insn->op_str, *code, skipdata_bytes);
2041#endif
2042
2043		*code += skipdata_bytes;
2044		*size -= skipdata_bytes;
2045		*address += skipdata_bytes;
2046	}
2047
2048	return true;
2049}
2050```
2051
2052</details>
2053
2054
2055<details><summary> 示例 </summary>
2056
2057```cpp
2058#include <iostream>
2059#include <stdio.h>
2060
2061#include "capstone.h"
2062#include "platform.h"
2063
2064using namespace std;
2065
2066struct platform {
2067	cs_arch arch;
2068	cs_mode mode;
2069	unsigned char* code;
2070	size_t size;
2071	const char* comment;
2072	cs_opt_type opt_type;
2073	cs_opt_value opt_value;
2074};
2075
2076static void print_string_hex(unsigned char* str, size_t len)
2077{
2078	unsigned char* c;
2079
2080	printf("Code: ");
2081	for (c = str; c < str + len; c++) {
2082		printf("0x%02x ", *c & 0xff);
2083	}
2084	printf("\n");
2085}
2086
2087static void test()
2088{
2089#define X86_CODE16 "\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00"
2090#define X86_CODE32 "\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00"
2091#define X86_CODE64 "\x55\x48\x8b\x05\xb8\x13\x00\x00"
2092
2093	struct platform platforms[4] = {     //架构及模式
2094		{
2095			CS_ARCH_X86,
2096			CS_MODE_16,
2097			(unsigned char*)X86_CODE16,
2098			sizeof(X86_CODE32) - 1,
2099			"X86 16bit (Intel syntax)"
2100		},
2101		{
2102			CS_ARCH_X86,
2103			CS_MODE_32,
2104			(unsigned char*)X86_CODE32,
2105			sizeof(X86_CODE32) - 1,
2106			"X86 32bit (ATT syntax)",
2107			CS_OPT_SYNTAX,
2108			CS_OPT_SYNTAX_ATT,
2109		},
2110		{
2111			CS_ARCH_X86,
2112			CS_MODE_32,
2113			(unsigned char*)X86_CODE32,
2114			sizeof(X86_CODE32) - 1,
2115			"X86 32 (Intel syntax)"
2116		},
2117		{
2118			CS_ARCH_X86,
2119			CS_MODE_64,
2120			(unsigned char*)X86_CODE64,
2121			sizeof(X86_CODE64) - 1,
2122			"X86 64 (Intel syntax)"
2123		},
2124
2125	csh handle;
2126	uint64_t address;
2127	cs_insn* insn;
2128	cs_detail* detail;
2129	int i;
2130	cs_err err;
2131	const uint8_t* code;
2132	size_t size;
2133
2134	for (i = 0; i < sizeof(platforms) / sizeof(platforms[0]); i++) {
2135		printf("****************\n");
2136		printf("Platform: %s\n", platforms[i].comment);
2137		err = cs_open(platforms[i].arch, platforms[i].mode, &handle);
2138		if (err) {
2139			printf("Failed on cs_open() with error returned: %u\n", err);
2140			abort();
2141		}
2142
2143		if (platforms[i].opt_type)
2144			cs_option(handle, platforms[i].opt_type, platforms[i].opt_value);
2145
2146		cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
2147
2148		// 为cs_disasm_iter()分配内存
2149		insn = cs_malloc(handle);
2150
2151		print_string_hex(platforms[i].code, platforms[i].size);   //原机器码
2152		printf("Disasm:\n");
2153
2154		address = 0x1000;
2155		code = platforms[i].code;
2156		size = platforms[i].size;
2157		while (cs_disasm_iter(handle, &code, &size, &address, insn)) {   //cs_disasm_iter反汇编
2158			int n;
2159
2160			printf("0x%" PRIx64 ":\t%s\t\t%s // insn-ID: %u, insn-mnem: %s\n",
2161				insn->address, insn->mnemonic, insn->op_str,
2162				insn->id, cs_insn_name(handle, insn->id));
2163
2164			// 打印此指令使用的隐式寄存器
2165			detail = insn->detail;
2166
2167			if (detail->regs_read_count > 0) {
2168				printf("\tImplicit registers read: ");
2169				for (n = 0; n < detail->regs_read_count; n++) {
2170					printf("%s ", cs_reg_name(handle, detail->regs_read[n]));
2171				}
2172				printf("\n");
2173			}
2174
2175			// 打印此指令修改的隐式寄存器
2176			if (detail->regs_write_count > 0) {
2177				printf("\tImplicit registers modified: ");
2178				for (n = 0; n < detail->regs_write_count; n++) {
2179					printf("%s ", cs_reg_name(handle, detail->regs_write[n]));
2180				}
2181				printf("\n");
2182			}
2183
2184			// 打印此指令所属指令集
2185			if (detail->groups_count > 0) {
2186				printf("\tThis instruction belongs to groups: ");
2187				for (n = 0; n < detail->groups_count; n++) {
2188					printf("%s ", cs_group_name(handle, detail->groups[n]));
2189				}
2190				printf("\n");
2191			}
2192		}
2193
2194		printf("\n");
2195
2196		// 释放cs_malloc()分配的内存
2197		cs_free(insn, 1);
2198
2199		cs_close(&handle);
2200	}
2201}
2202
2203int main()
2204{
2205	test();
2206
2207	return 0;
2208}
2209```
2210
2211</details>
2212
2213输出
2214
2215![](API_Doc_Pic/20.jpg)
2216
2217
2218### cs_reg_name
2219
2220`const char * CAPSTONE_API cs_reg_name(csh handle, unsigned int reg_id);`
2221
2222获取寄存器的名字(string类型)
2223寄存器id可在相关架构的头文件(建立项目时复制到项目文件夹的那些头文件)内找到
2224
2225注意: 当处于diet模式时此API不可用,因为引擎不会存储寄存器名
2226
2227```
2228handle: cs_open()返回的句柄
2229reg_id: 寄存器id
2230return: 寄存器的字符名, 如果reg_id不可用返回NULL
2231```
2232
2233<details><summary> 源码实现 </summary>
2234
2235```cpp
2236const char * CAPSTONE_API cs_reg_name(csh ud, unsigned int reg)
2237{
2238	struct cs_struct *handle = (struct cs_struct *)(uintptr_t)ud;
2239
2240	if (!handle || handle->reg_name == NULL) {
2241		return NULL;
2242	}
2243
2244	return handle->reg_name(ud, reg);
2245}
2246```
2247
2248</details>
2249
2250
2251<details><summary> 示例(打印RAX) </summary>
2252
2253```cpp
2254#include <iostream>
2255#include <stdio.h>
2256
2257#include "capstone.h"
2258#include "platform.h"
2259
2260using namespace std;
2261
2262int main(void)
2263{
2264	csh handle = 0;
2265	cs_insn* insn;
2266	size_t count;
2267
2268	if (cs_open(CS_ARCH_X86, CS_MODE_64, &handle)) {
2269		printf("ERROR: Failed to initialize engine!\n");
2270		return -1;
2271	}
2272
2273	printf("%s", cs_reg_name(handle, X86_REG_RAX));
2274	cs_close(&handle);
2275
2276	return 0;
2277}
2278```
2279
2280</details>
2281
2282输出
2283
2284![](API_Doc_Pic/21.jpg)
2285
2286
2287### cs_insn_name
2288
2289`const char * CAPSTONE_API cs_insn_name(csh handle, unsigned int insn_id);`
2290
2291获取指令的名字(string类型)
2292
2293指令id可在相关架构的头文件(建立项目时复制到项目文件夹的那些头文件)内找到
2294
2295注意: 当处于diet模式时此API不可用,因为引擎不会存储寄存器名
2296
2297```
2298handle: cs_open()返回的句柄
2299insn_id: 指令id
2300return: 指令的字符名, 如果insn_id不可用返回NULL
2301```
2302
2303<details><summary> 源码实现 </summary>
2304
2305```cpp
2306const char * CAPSTONE_API cs_insn_name(csh ud, unsigned int insn)
2307{
2308	struct cs_struct *handle = (struct cs_struct *)(uintptr_t)ud;
2309
2310	if (!handle || handle->insn_name == NULL) {
2311		return NULL;
2312	}
2313
2314	return handle->insn_name(ud, insn);
2315}
2316```
2317
2318</details>
2319
2320
2321<details><summary> 示例 </summary>
2322
2323```cpp
2324#include <iostream>
2325#include <stdio.h>
2326
2327#include "capstone.h"
2328#include "platform.h"
2329
2330using namespace std;
2331
2332struct platform {
2333	cs_arch arch;
2334	cs_mode mode;
2335	unsigned char* code;
2336	size_t size;
2337	const char* comment;
2338	cs_opt_type opt_type;
2339	cs_opt_value opt_value;
2340};
2341
2342static void print_string_hex(unsigned char* str, size_t len)
2343{
2344	unsigned char* c;
2345
2346	printf("Code: ");
2347	for (c = str; c < str + len; c++) {
2348		printf("0x%02x ", *c & 0xff);
2349	}
2350	printf("\n");
2351}
2352
2353static void test()
2354{
2355
2356#define X86_CODE64 "\x55\x48\x8b\x05\xb8\x13\x00\x00\xe9\xea\xbe\xad\xde\xff\x25\x23\x01\x00\x00\xe8\xdf\xbe\xad\xde\x74\xff"
2357
2358	struct platform platforms[] = {
2359		{
2360			CS_ARCH_X86,
2361			CS_MODE_64,
2362			(unsigned char*)X86_CODE64,
2363			sizeof(X86_CODE64) - 1,
2364			"X86 64 (Intel syntax)"
2365		},
2366	};
2367
2368	csh handle;
2369	uint64_t address;
2370	cs_insn* insn;
2371	cs_detail* detail;
2372	int i;
2373	cs_err err;
2374	const uint8_t* code;
2375	size_t size;
2376
2377	for (i = 0; i < sizeof(platforms) / sizeof(platforms[0]); i++) {
2378		printf("****************\n");
2379		printf("Platform: %s\n", platforms[i].comment);
2380		err = cs_open(platforms[i].arch, platforms[i].mode, &handle);
2381		if (err) {
2382			printf("Failed on cs_open() with error returned: %u\n", err);
2383			abort();
2384		}
2385
2386		if (platforms[i].opt_type)
2387			cs_option(handle, platforms[i].opt_type, platforms[i].opt_value);
2388
2389		cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
2390
2391		insn = cs_malloc(handle);
2392
2393		print_string_hex(platforms[i].code, platforms[i].size);
2394		printf("Disasm:\n");
2395
2396		address = 0x1000;
2397		code = platforms[i].code;
2398		size = platforms[i].size;
2399		while (cs_disasm_iter(handle, &code, &size, &address, insn)) {
2400			int n;
2401
2402			printf("0x%" PRIx64 ":\t%s\t\t%s",
2403				insn->address, insn->mnemonic, insn->op_str);
2404			printf("            instruction:  %s", cs_insn_name(handle, insn->id));   //输出该行的操作指令
2405			cout << endl;
2406
2407		printf("\n");
2408		cs_free(insn, 1);
2409		cs_close(&handle);
2410	}
2411}
2412
2413int main()
2414{
2415	test();
2416
2417	return 0;
2418}
2419```
2420
2421</details>
2422
2423输出
2424
2425![](API_Doc_Pic/22.jpg)
2426
2427
2428### cs_group_name
2429
2430`const char * CAPSTONE_API cs_group_name(csh handle, unsigned int group_id);`
2431
2432输出指令类型名字
2433
2434指令id可在相关架构的头文件(建立项目时复制到项目文件夹的那些头文件)内找到
2435
2436注意: 当处于diet模式时此API不可用,因为引擎不会存储寄存器名
2437
2438```
2439handle: cs_open()返回的句柄
2440insn_id: 指令类型id
2441return: 指令类型的字符名, 如果insn_id不可用返回NULL
2442```
2443
2444示例都与上面类似,略。
2445
2446
2447### cs_insn_group
2448
2449`bool CAPSTONE_API cs_insn_group(csh handle, const cs_insn *insn, unsigned int group_id);`
2450
2451检查反汇编后的指令是否属于某个特定指令类型
2452
2453注意:只有当detail选项为ON时这个API可用 (默认OFF).
2454
2455在“diet”模式下,此API没有用,因为引擎不更新insn->groups数组
2456
2457```
2458handle: cs_open()返回的句柄
2459insn: 从cs_disasm()或cs_disasm_iter()接收的反汇编指令结构
2460group_id: 要检查此指令是否属于的指令类型。
2461return: 如果该指令确实属于给定的指令类型,则为true,否则为false。
2462```
2463
2464<details><summary> 源码实现 </summary>
2465
2466```cpp
2467bool CAPSTONE_API cs_insn_group(csh ud, const cs_insn *insn, unsigned int group_id)
2468{
2469	struct cs_struct *handle;
2470	if (!ud)
2471		return false;
2472
2473	handle = (struct cs_struct *)(uintptr_t)ud;
2474
2475	if (!handle->detail) {
2476		handle->errnum = CS_ERR_DETAIL;
2477		return false;
2478	}
2479
2480	if (!insn->id) {
2481		handle->errnum = CS_ERR_SKIPDATA;
2482		return false;
2483	}
2484
2485	if (!insn->detail) {
2486		handle->errnum = CS_ERR_DETAIL;
2487		return false;
2488	}
2489
2490	return arr_exist8(insn->detail->groups, insn->detail->groups_count, group_id);
2491}
2492```
2493
2494</details>
2495
2496
2497<details><summary> 示例(判断是否属于跳转指令) </summary>
2498
2499```cpp
2500#include <iostream>
2501#include <stdio.h>
2502
2503#include "capstone.h"
2504#include "platform.h"
2505
2506using namespace std;
2507
2508struct platform {
2509	cs_arch arch;
2510	cs_mode mode;
2511	unsigned char* code;
2512	size_t size;
2513	const char* comment;
2514	cs_opt_type opt_type;
2515	cs_opt_value opt_value;
2516};
2517
2518static void print_string_hex(unsigned char* str, size_t len)
2519{
2520	unsigned char* c;
2521
2522	printf("Code: ");
2523	for (c = str; c < str + len; c++) {
2524		printf("0x%02x ", *c & 0xff);
2525	}
2526	printf("\n");
2527}
2528
2529static void test()
2530{
2531
2532#define X86_CODE64 "\x55\x48\x8b\x05\xb8\x13\x00\x00\xe9\xea\xbe\xad\xde\xff\x25\x23\x01\x00\x00\xe8\xdf\xbe\xad\xde\x74\xff"
2533
2534	struct platform platforms[] = {
2535		{
2536			CS_ARCH_X86,
2537			CS_MODE_64,
2538			(unsigned char*)X86_CODE64,
2539			sizeof(X86_CODE64) - 1,
2540			"X86 64 (Intel syntax)"
2541		},
2542	};
2543
2544	csh handle;
2545	uint64_t address;
2546	cs_insn* insn;
2547	cs_detail* detail;
2548	int i;
2549	cs_err err;
2550	const uint8_t* code;
2551	size_t size;
2552
2553	for (i = 0; i < sizeof(platforms) / sizeof(platforms[0]); i++) {
2554		printf("****************\n");
2555		printf("Platform: %s\n", platforms[i].comment);
2556		err = cs_open(platforms[i].arch, platforms[i].mode, &handle);
2557		if (err) {
2558			printf("Failed on cs_open() with error returned: %u\n", err);
2559			abort();
2560		}
2561
2562		if (platforms[i].opt_type)
2563			cs_option(handle, platforms[i].opt_type, platforms[i].opt_value);
2564
2565		cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
2566
2567		insn = cs_malloc(handle);
2568
2569		print_string_hex(platforms[i].code, platforms[i].size);
2570		printf("Disasm:\n");
2571
2572		address = 0x1000;
2573		code = platforms[i].code;
2574		size = platforms[i].size;
2575		while (cs_disasm_iter(handle, &code, &size, &address, insn)) {
2576			int n;
2577
2578			printf("0x%" PRIx64 ":\t%s\t\t%s          ",
2579				insn->address, insn->mnemonic, insn->op_str);
2580			cout << "is JUMP:   " <<cs_insn_group(handle, insn, CS_GRP_JUMP) << endl;   //判断是否为跳转指令
2581			cout << endl;
2582
2583		printf("\n");
2584		cs_free(insn, 1);
2585		cs_close(&handle);
2586	}
2587}
2588
2589int main()
2590{
2591	test();
2592
2593	return 0;
2594}
2595```
2596
2597</details>
2598
2599输出
2600
2601![](API_Doc_Pic/23.jpg)
2602
2603
2604### cs_reg_read
2605
2606`bool CAPSTONE_API cs_reg_read(csh handle, const cs_insn *insn, unsigned int reg_id);`
2607
2608检查反汇编指令是否隐式使用特定寄存器。
2609
2610注意:此API仅在启用detail选项时有效(默认为关闭)
2611
2612在“diet”模式下,此API没有用,因为引擎不更新insn->regs_read数组
2613
2614```
2615insn: 从cs_disasm()或cs_disasm_iter()接收的反汇编指令结构
2616reg_id: 标注想要检查的这个指令是否使用了它。
2617return: 如果该指令确实隐式使用了给定寄存器,则为true,否则为false。
2618```
2619
2620<details><summary> 源码实现 </summary>
2621
2622```cpp
2623bool CAPSTONE_API cs_reg_read(csh ud, const cs_insn *insn, unsigned int reg_id)
2624{
2625	struct cs_struct *handle;
2626	if (!ud)
2627		return false;
2628
2629	handle = (struct cs_struct *)(uintptr_t)ud;
2630
2631	if (!handle->detail) {
2632		handle->errnum = CS_ERR_DETAIL;
2633		return false;
2634	}
2635
2636	if (!insn->id) {
2637		handle->errnum = CS_ERR_SKIPDATA;
2638		return false;
2639	}
2640
2641	if (!insn->detail) {
2642		handle->errnum = CS_ERR_DETAIL;
2643		return false;
2644	}
2645
2646	return arr_exist(insn->detail->regs_read, insn->detail->regs_read_count, reg_id);
2647}
2648```
2649</details>
2650
2651示例同API cs_disasm_iter
2652
2653
2654### cs_reg_write
2655
2656`bool CAPSTONE_API cs_reg_write(csh handle, const cs_insn *insn, unsigned int reg_id);`
2657
2658检查反汇编指令是否隐式修改了特定寄存器。
2659
2660注意:此API仅在启用detail选项时有效(默认为关闭)
2661
2662在“diet”模式下,此API没有用,因为引擎不更新insn->regs_read数组
2663
2664```
2665insn: 从cs_disasm()或cs_disasm_iter()接收的反汇编指令结构
2666reg_id: 标注想要检查的这个指令是否修改了它。
2667return: 如果该指令确实隐式修改了给定寄存器,则为true,否则为false。
2668```
2669
2670<details><summary> 源码实现 </summary>
2671
2672```cpp
2673bool CAPSTONE_API cs_reg_write(csh ud, const cs_insn *insn, unsigned int reg_id)
2674{
2675	struct cs_struct *handle;
2676	if (!ud)
2677		return false;
2678
2679	handle = (struct cs_struct *)(uintptr_t)ud;
2680
2681	if (!handle->detail) {
2682		handle->errnum = CS_ERR_DETAIL;
2683		return false;
2684	}
2685
2686	if (!insn->id) {
2687		handle->errnum = CS_ERR_SKIPDATA;
2688		return false;
2689	}
2690
2691	if (!insn->detail) {
2692		handle->errnum = CS_ERR_DETAIL;
2693		return false;
2694	}
2695
2696	return arr_exist(insn->detail->regs_write, insn->detail->regs_write_count, reg_id);
2697}
2698```
2699</details>
2700
2701示例同API cs_disasm_iter
2702
2703
2704### cs_op_count
2705
2706`int CAPSTONE_API cs_op_count(csh handle, const cs_insn *insn, unsigned int op_type);`
2707
2708计算给定类型的操作数的数量
2709
2710注意:只有当detail选项为ON时这个API可用 (默认OFF).
2711
2712```
2713handle: cs_open()返回的句柄
2714insn: 从cs_disasm()或cs_disasm_iter()接收的反汇编指令结构
2715op_type: 要找到的操作数类型。
2716return: 指令insn中给定类型op_type的操作数的数量,返回-1表示查找失败。
2717```
2718
2719<details><summary> 源码实现 </summary>
2720
2721```cpp
2722int CAPSTONE_API cs_op_count(csh ud, const cs_insn *insn, unsigned int op_type)
2723{
2724	struct cs_struct *handle;
2725	unsigned int count = 0, i;
2726	if (!ud)
2727		return -1;
2728
2729	handle = (struct cs_struct *)(uintptr_t)ud;
2730
2731	if (!handle->detail) {
2732		handle->errnum = CS_ERR_DETAIL;
2733		return -1;
2734	}
2735
2736	if (!insn->id) {
2737		handle->errnum = CS_ERR_SKIPDATA;
2738		return -1;
2739	}
2740
2741	if (!insn->detail) {
2742		handle->errnum = CS_ERR_DETAIL;
2743		return -1;
2744	}
2745
2746	handle->errnum = CS_ERR_OK;
2747
2748	switch (handle->arch) {
2749		default:
2750			handle->errnum = CS_ERR_HANDLE;
2751			return -1;
2752		case CS_ARCH_ARM:
2753			for (i = 0; i < insn->detail->arm.op_count; i++)
2754				if (insn->detail->arm.operands[i].type == (arm_op_type)op_type)
2755					count++;
2756			break;
2757		case CS_ARCH_ARM64:
2758			for (i = 0; i < insn->detail->arm64.op_count; i++)
2759				if (insn->detail->arm64.operands[i].type == (arm64_op_type)op_type)
2760					count++;
2761			break;
2762		case CS_ARCH_X86:
2763			for (i = 0; i < insn->detail->x86.op_count; i++)
2764				if (insn->detail->x86.operands[i].type == (x86_op_type)op_type)
2765					count++;
2766			break;
2767		case CS_ARCH_MIPS:
2768			for (i = 0; i < insn->detail->mips.op_count; i++)
2769				if (insn->detail->mips.operands[i].type == (mips_op_type)op_type)
2770					count++;
2771			break;
2772		case CS_ARCH_PPC:
2773			for (i = 0; i < insn->detail->ppc.op_count; i++)
2774				if (insn->detail->ppc.operands[i].type == (ppc_op_type)op_type)
2775					count++;
2776			break;
2777		case CS_ARCH_SPARC:
2778			for (i = 0; i < insn->detail->sparc.op_count; i++)
2779				if (insn->detail->sparc.operands[i].type == (sparc_op_type)op_type)
2780					count++;
2781			break;
2782		case CS_ARCH_SYSZ:
2783			for (i = 0; i < insn->detail->sysz.op_count; i++)
2784				if (insn->detail->sysz.operands[i].type == (sysz_op_type)op_type)
2785					count++;
2786			break;
2787		case CS_ARCH_XCORE:
2788			for (i = 0; i < insn->detail->xcore.op_count; i++)
2789				if (insn->detail->xcore.operands[i].type == (xcore_op_type)op_type)
2790					count++;
2791			break;
2792		case CS_ARCH_M68K:
2793			for (i = 0; i < insn->detail->m68k.op_count; i++)
2794				if (insn->detail->m68k.operands[i].type == (m68k_op_type)op_type)
2795					count++;
2796			break;
2797		case CS_ARCH_TMS320C64X:
2798			for (i = 0; i < insn->detail->tms320c64x.op_count; i++)
2799				if (insn->detail->tms320c64x.operands[i].type == (tms320c64x_op_type)op_type)
2800					count++;
2801			break;
2802		case CS_ARCH_M680X:
2803			for (i = 0; i < insn->detail->m680x.op_count; i++)
2804				if (insn->detail->m680x.operands[i].type == (m680x_op_type)op_type)
2805					count++;
2806			break;
2807		case CS_ARCH_EVM:
2808#if 0
2809			for (i = 0; i < insn->detail->evm.op_count; i++)
2810				if (insn->detail->evm.operands[i].type == (evm_op_type)op_type)
2811					count++;
2812#endif
2813			break;
2814	}
2815
2816	return count;
2817}
2818```
2819
2820</details>
2821
2822
2823<details><summary> x86指令操作码类型示例(判断寄存操作码) </summary>
2824
2825```cpp
2826typedef enum x86_op_type {
2827	X86_OP_INVALID = 0, ///< = CS_OP_INVALID (未初始化).
2828	X86_OP_REG, ///< = CS_OP_REG (寄存操作码).
2829	X86_OP_IMM, ///< = CS_OP_IMM (立即操作码).
2830	X86_OP_MEM, ///< = CS_OP_MEM (内存操作码).
2831} x86_op_type;
2832```
2833
2834```cpp
2835#include <iostream>
2836#include <stdio.h>
2837
2838#include "capstone.h"
2839#include "platform.h"
2840
2841using namespace std;
2842
2843struct platform {
2844	cs_arch arch;
2845	cs_mode mode;
2846	unsigned char* code;
2847	size_t size;
2848	const char* comment;
2849	cs_opt_type opt_type;
2850	cs_opt_value opt_value;
2851};
2852
2853static void print_string_hex(unsigned char* str, size_t len)
2854{
2855	unsigned char* c;
2856
2857	printf("Code: ");
2858	for (c = str; c < str + len; c++) {
2859		printf("0x%02x ", *c & 0xff);
2860	}
2861	printf("\n");
2862}
2863
2864static void test()
2865{
2866
2867#define X86_CODE64 "\x55\x48\x8b\x05\xb8\x13\x00\x00\xe9\xea\xbe\xad\xde\xff\x25\x23\x01\x00\x00\xe8\xdf\xbe\xad\xde\x74\xff"
2868
2869	struct platform platforms[] = {
2870		{
2871			CS_ARCH_X86,
2872			CS_MODE_64,
2873			(unsigned char*)X86_CODE64,
2874			sizeof(X86_CODE64) - 1,
2875			"X86 64 (Intel syntax)"
2876		},
2877	};
2878
2879	csh handle;
2880	uint64_t address;
2881	cs_insn* insn;
2882	cs_detail* detail;
2883	int i;
2884	cs_err err;
2885	const uint8_t* code;
2886	size_t size;
2887
2888	for (i = 0; i < sizeof(platforms) / sizeof(platforms[0]); i++) {
2889		printf("****************\n");
2890		printf("Platform: %s\n", platforms[i].comment);
2891		err = cs_open(platforms[i].arch, platforms[i].mode, &handle);
2892		if (err) {
2893			printf("Failed on cs_open() with error returned: %u\n", err);
2894			abort();
2895		}
2896
2897		if (platforms[i].opt_type)
2898			cs_option(handle, platforms[i].opt_type, platforms[i].opt_value);
2899
2900		cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
2901
2902		insn = cs_malloc(handle);
2903
2904		print_string_hex(platforms[i].code, platforms[i].size);
2905		printf("Disasm:\n");
2906
2907		address = 0x1000;
2908		code = platforms[i].code;
2909		size = platforms[i].size;
2910		while (cs_disasm_iter(handle, &code, &size, &address, insn)) {
2911			int n;
2912
2913			printf("0x%" PRIx64 ":\t%s\t\t%s          ",
2914				insn->address, insn->mnemonic, insn->op_str);
2915			cout << "is REG:   " << cs_op_count(handle, insn, X86_OP_REG) << endl;   //判断是否为寄存操作码
2916			cout << endl;
2917
2918		printf("\n");
2919		cs_free(insn, 1);
2920		cs_close(&handle);
2921	}
2922}
2923
2924int main()
2925{
2926	test();
2927
2928	return 0;
2929}
2930```
2931
2932</details>
2933
2934输出
2935
2936![](API_Doc_Pic/24.jpg)
2937
2938
2939### cs_op_index
2940
2941`int CAPSTONE_API cs_op_index(csh handle, const cs_insn *insn, unsigned int op_type, unsigned int position);`
2942
2943检索给定类型的操作数在`<arch>.operands[]`数组中的位置, 使用返回的位置访问操作数
2944
2945注意:只有当detail选项为ON时这个API可用 (默认OFF).
2946
2947```
2948handle: cs_open()返回的句柄
2949insn: 从cs_disasm()或cs_disasm_iter()接收的反汇编指令结构
2950op_type: 要找到的操作数类型。
2951position: 要查找的操作数的位置。范围一定在`[1, cs_op_count(handle, insn, op_type)]`内
2952return: 指令insn的`<arch>.operands[]`数组中给定类型op_type的操作数的索引,失败时返回-1。
2953```
2954
2955<details><summary> 源码实现 </summary>
2956
2957```cpp
2958int CAPSTONE_API cs_op_index(csh ud, const cs_insn *insn, unsigned int op_type,
2959		unsigned int post)
2960{
2961	struct cs_struct *handle;
2962	unsigned int count = 0, i;
2963	if (!ud)
2964		return -1;
2965
2966	handle = (struct cs_struct *)(uintptr_t)ud;
2967
2968	if (!handle->detail) {
2969		handle->errnum = CS_ERR_DETAIL;
2970		return -1;
2971	}
2972
2973	if (!insn->id) {
2974		handle->errnum = CS_ERR_SKIPDATA;
2975		return -1;
2976	}
2977
2978	if (!insn->detail) {
2979		handle->errnum = CS_ERR_DETAIL;
2980		return -1;
2981	}
2982
2983	handle->errnum = CS_ERR_OK;
2984
2985	switch (handle->arch) {
2986		default:
2987			handle->errnum = CS_ERR_HANDLE;
2988			return -1;
2989		case CS_ARCH_ARM:
2990			for (i = 0; i < insn->detail->arm.op_count; i++) {
2991				if (insn->detail->arm.operands[i].type == (arm_op_type)op_type)
2992					count++;
2993				if (count == post)
2994					return i;
2995			}
2996			break;
2997		case CS_ARCH_ARM64:
2998			for (i = 0; i < insn->detail->arm64.op_count; i++) {
2999				if (insn->detail->arm64.operands[i].type == (arm64_op_type)op_type)
3000					count++;
3001				if (count == post)
3002					return i;
3003			}
3004			break;
3005		case CS_ARCH_X86:
3006			for (i = 0; i < insn->detail->x86.op_count; i++) {
3007				if (insn->detail->x86.operands[i].type == (x86_op_type)op_type)
3008					count++;
3009				if (count == post)
3010					return i;
3011			}
3012			break;
3013		case CS_ARCH_MIPS:
3014			for (i = 0; i < insn->detail->mips.op_count; i++) {
3015				if (insn->detail->mips.operands[i].type == (mips_op_type)op_type)
3016					count++;
3017				if (count == post)
3018					return i;
3019			}
3020			break;
3021		case CS_ARCH_PPC:
3022			for (i = 0; i < insn->detail->ppc.op_count; i++) {
3023				if (insn->detail->ppc.operands[i].type == (ppc_op_type)op_type)
3024					count++;
3025				if (count == post)
3026					return i;
3027			}
3028			break;
3029		case CS_ARCH_SPARC:
3030			for (i = 0; i < insn->detail->sparc.op_count; i++) {
3031				if (insn->detail->sparc.operands[i].type == (sparc_op_type)op_type)
3032					count++;
3033				if (count == post)
3034					return i;
3035			}
3036			break;
3037		case CS_ARCH_SYSZ:
3038			for (i = 0; i < insn->detail->sysz.op_count; i++) {
3039				if (insn->detail->sysz.operands[i].type == (sysz_op_type)op_type)
3040					count++;
3041				if (count == post)
3042					return i;
3043			}
3044			break;
3045		case CS_ARCH_XCORE:
3046			for (i = 0; i < insn->detail->xcore.op_count; i++) {
3047				if (insn->detail->xcore.operands[i].type == (xcore_op_type)op_type)
3048					count++;
3049				if (count == post)
3050					return i;
3051			}
3052			break;
3053		case CS_ARCH_M68K:
3054			for (i = 0; i < insn->detail->m68k.op_count; i++) {
3055				if (insn->detail->m68k.operands[i].type == (m68k_op_type)op_type)
3056					count++;
3057				if (count == post)
3058					return i;
3059			}
3060			break;
3061		case CS_ARCH_TMS320C64X:
3062			for (i = 0; i < insn->detail->tms320c64x.op_count; i++) {
3063				if (insn->detail->tms320c64x.operands[i].type == (tms320c64x_op_type)op_type)
3064					count++;
3065				if (count == post)
3066					return i;
3067			}
3068			break;
3069		case CS_ARCH_M680X:
3070			for (i = 0; i < insn->detail->m680x.op_count; i++) {
3071				if (insn->detail->m680x.operands[i].type == (m680x_op_type)op_type)
3072					count++;
3073				if (count == post)
3074					return i;
3075			}
3076			break;
3077	}
3078
3079	return -1;
3080}
3081```
3082</details>
3083
3084
3085<details><summary> 示例 </summary>
3086
3087```cpp
3088#include <iostream>
3089#include <stdio.h>
3090
3091#include "capstone.h"
3092#include "platform.h"
3093
3094using namespace std;
3095
3096struct platform {
3097	cs_arch arch;
3098	cs_mode mode;
3099	unsigned char* code;
3100	size_t size;
3101	const char* comment;
3102	cs_opt_type opt_type;
3103	cs_opt_value opt_value;
3104};
3105
3106static void print_string_hex(unsigned char* str, size_t len)
3107{
3108	unsigned char* c;
3109
3110	printf("Code: ");
3111	for (c = str; c < str + len; c++) {
3112		printf("0x%02x ", *c & 0xff);
3113	}
3114	printf("\n");
3115}
3116
3117static void test()
3118{
3119#define X86_CODE64 "\x55\x48\x8b\x05\xb8\x13\x00\x00\xe9\xea\xbe\xad\xde\xff\x25\x23\x01\x00\x00\xe8\xdf\xbe\xad\xde\x74\xff"
3120	struct platform platforms[] = {
3121		{
3122			CS_ARCH_X86,
3123			CS_MODE_64,
3124			(unsigned char*)X86_CODE64,
3125			sizeof(X86_CODE64) - 1,
3126			"X86 64 (Intel syntax)"
3127		},
3128	};
3129
3130	csh handle;
3131	uint64_t address;
3132	cs_insn* insn;
3133	cs_detail* detail;
3134	int i;
3135	cs_err err;
3136	const uint8_t* code;
3137	size_t size;
3138
3139	cs_x86* x86;
3140
3141	int count;
3142
3143	for (i = 0; i < sizeof(platforms) / sizeof(platforms[0]); i++) {
3144		printf("****************\n");
3145		printf("Platform: %s\n", platforms[i].comment);
3146		err = cs_open(platforms[i].arch, platforms[i].mode, &handle);
3147		if (err) {
3148			printf("Failed on cs_open() with error returned: %u\n", err);
3149			abort();
3150		}
3151
3152		if (platforms[i].opt_type)
3153			cs_option(handle, platforms[i].opt_type, platforms[i].opt_value);
3154
3155		cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
3156
3157		insn = cs_malloc(handle);
3158		x86 = &(insn->detail->x86);
3159		print_string_hex(platforms[i].code, platforms[i].size);
3160		printf("Disasm:\n");
3161
3162		address = 0x1000;
3163		code = platforms[i].code;
3164		size = platforms[i].size;
3165		while (cs_disasm_iter(handle, &code, &size, &address, insn)) {
3166			int n;
3167
3168			printf("0x%" PRIx64 ":\t%s\t\t%s          ",
3169				insn->address, insn->mnemonic, insn->op_str);
3170			cout << endl;
3171
3172			count = cs_op_count(handle, insn, X86_OP_IMM);  //查找立即数
3173			if (count) {
3174				printf("\timm_count: %u\n", count);
3175				for (i = 1; i < count + 1; i++) {
3176					int index = cs_op_index(handle, insn, X86_OP_IMM, i);
3177					printf("\timms[%u]: 0x%" PRIx64 "\n", i, x86->operands[index].imm);
3178					if (x86->encoding.imm_offset != 0) {
3179						printf("\timm_offset: 0x%x\n", x86->encoding.imm_offset);
3180					}
3181					if (x86->encoding.imm_size != 0) {
3182						printf("\timm_size: 0x%x\n", x86->encoding.imm_size);
3183					}
3184				}
3185			}
3186		}
3187
3188		printf("\n");
3189		cs_free(insn, 1);
3190		cs_close(&handle);
3191	}
3192}
3193
3194int main()
3195{
3196	test();
3197	return 0;
3198}
3199```
3200
3201</details>
3202
3203输出
3204![](API_Doc_Pic/25.jpg)
3205
3206
3207### cs_regs_access
3208
3209```cpp
3210cs_err CAPSTONE_API cs_regs_access(csh handle, const cs_insn *insn,
3211		cs_regs regs_read, uint8_t *regs_read_count,
3212		cs_regs regs_write, uint8_t *regs_write_count);
3213```
3214
3215检索由一条指令显式或隐式访问的所有寄存器
3216
3217注意: 在“diet”模式下,此API不可用,因为引擎不存储寄存器
3218
3219```
3220handle: cs_open()返回的句柄
3221insn: 从cs_disasm()或cs_disasm_iter()返回的反汇编指令结构
3222regs_read:返回时,这个数组包含所有按指令读取的寄存器。
3223regs_read_count:保存在regs_read数组中的寄存器数。
3224regs_write:返回时,这个数组包含所有由指令修改的寄存器。
3225regs_write_count:保存在regs_write数组中的寄存器数。
3226成功时返回CS_ERR_OK,失败时返回其他值(详细错误请参阅cs_err enum)。
3227```
3228
3229<details><summary> 源码实现 </summary>
3230
3231```cpp
3232cs_err CAPSTONE_API cs_regs_access(csh ud, const cs_insn *insn,
3233		cs_regs regs_read, uint8_t *regs_read_count,
3234		cs_regs regs_write, uint8_t *regs_write_count)
3235{
3236	struct cs_struct *handle;
3237
3238	if (!ud)
3239		return -1;
3240
3241	handle = (struct cs_struct *)(uintptr_t)ud;
3242
3243#ifdef CAPSTONE_DIET
3244	// This API does not work in DIET mode
3245	handle->errnum = CS_ERR_DIET;
3246	return CS_ERR_DIET;
3247#else
3248	if (!handle->detail) {
3249		handle->errnum = CS_ERR_DETAIL;
3250		return CS_ERR_DETAIL;
3251	}
3252
3253	if (!insn->id) {
3254		handle->errnum = CS_ERR_SKIPDATA;
3255		return CS_ERR_SKIPDATA;
3256	}
3257
3258	if (!insn->detail) {
3259		handle->errnum = CS_ERR_DETAIL;
3260		return CS_ERR_DETAIL;
3261	}
3262
3263	if (handle->reg_access) {
3264		handle->reg_access(insn, regs_read, regs_read_count, regs_write, regs_write_count);
3265	} else {
3266		// this arch is unsupported yet
3267		handle->errnum = CS_ERR_ARCH;
3268		return CS_ERR_ARCH;
3269	}
3270
3271	return CS_ERR_OK;
3272#endif
3273}
3274```
3275
3276</details>
3277
3278
3279<details><summary> 示例 </summary>
3280
3281```cpp
3282#include <iostream>
3283#include <stdio.h>
3284
3285#include "capstone.h"
3286#include "platform.h"
3287
3288using namespace std;
3289
3290struct platform {
3291	cs_arch arch;
3292	cs_mode mode;
3293	unsigned char* code;
3294	size_t size;
3295	const char* comment;
3296	cs_opt_type opt_type;
3297	cs_opt_value opt_value;
3298};
3299
3300static void print_string_hex(unsigned char* str, size_t len)
3301{
3302	unsigned char* c;
3303
3304	printf("Code: ");
3305	for (c = str; c < str + len; c++) {
3306		printf("0x%02x ", *c & 0xff);
3307	}
3308	printf("\n");
3309}
3310
3311static void test()
3312{
3313#define X86_CODE64 "\x55\x48\x8b\x05\xb8\x13\x00\x00\xe9\xea\xbe\xad\xde\xff\x25\x23\x01\x00\x00\xe8\xdf\xbe\xad\xde\x74\xff"
3314	struct platform platforms[] = {
3315		{
3316			CS_ARCH_X86,
3317			CS_MODE_64,
3318			(unsigned char*)X86_CODE64,
3319			sizeof(X86_CODE64) - 1,
3320			"X86 64 (Intel syntax)"
3321		},
3322	};
3323
3324	csh handle;
3325	uint64_t address;
3326	cs_insn* insn;
3327	cs_detail* detail;
3328	int i;
3329	cs_err err;
3330	const uint8_t* code;
3331	size_t size;
3332
3333	cs_x86* x86;
3334	cs_regs regs_read, regs_write;
3335	uint8_t regs_read_count, regs_write_count;
3336
3337	int count;
3338
3339	for (i = 0; i < sizeof(platforms) / sizeof(platforms[0]); i++) {
3340		printf("****************\n");
3341		printf("Platform: %s\n", platforms[i].comment);
3342		err = cs_open(platforms[i].arch, platforms[i].mode, &handle);
3343		if (err) {
3344			printf("Failed on cs_open() with error returned: %u\n", err);
3345			abort();
3346		}
3347
3348		if (platforms[i].opt_type)
3349			cs_option(handle, platforms[i].opt_type, platforms[i].opt_value);
3350
3351		cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
3352
3353		insn = cs_malloc(handle);
3354		x86 = &(insn->detail->x86);
3355		print_string_hex(platforms[i].code, platforms[i].size);
3356		printf("Disasm:\n");
3357
3358		address = 0x1000;
3359		code = platforms[i].code;
3360		size = platforms[i].size;
3361		while (cs_disasm_iter(handle, &code, &size, &address, insn)) {
3362			int n;
3363
3364			printf("0x%" PRIx64 ":\t%s\t\t%s          ",
3365				insn->address, insn->mnemonic, insn->op_str);
3366			cout << endl;
3367
3368			if (!cs_regs_access(handle, insn,       //每条指令所有读取和修改的寄存器
3369				regs_read, &regs_read_count,
3370				regs_write, &regs_write_count)) {
3371				if (regs_read_count) {
3372					printf("\tRegisters read:");
3373					for (i = 0; i < regs_read_count; i++) {
3374						printf(" %s", cs_reg_name(handle, regs_read[i]));
3375					}
3376					printf("\n");
3377				}
3378
3379				if (regs_write_count) {
3380					printf("\tRegisters modified:");
3381					for (i = 0; i < regs_write_count; i++) {
3382						printf(" %s", cs_reg_name(handle, regs_write[i]));
3383					}
3384					printf("\n");
3385				}
3386			}
3387		}
3388
3389		printf("\n");
3390		cs_free(insn, 1);
3391		cs_close(&handle);
3392	}
3393}
3394
3395int main()
3396{
3397	test();
3398	return 0;
3399}
3400```
3401
3402</details>
3403
3404输出
3405
3406![](API_Doc_Pic/26.jpg)
3407