assembly - x86 指令前缀解码
问题描述
我目前正在为 x86_x64 CISC 开发反汇编程序。我有两个关于前缀指令解码的问题:
对于以下流:
\x9b\x9b\xd9\x30
GCC
和objdump
输出fstenv [eax]
因此,他们首先读取所有前缀(不超过 15 个),然后使用读取的最后一个前缀继续检查正确的指令
\x9b
,\xd9
使其成为fstenv
指令。Capstone
另一方面输出wait wait fnstenv dword ptr [eax]
现在,很明显,它放置了 2
wait
条指令而不仅仅是 1 条指令是错误的。但它应该完全放置wait
指令,还是放在右边,以消耗指令的GCC
所有objdump
额外\x9b
前缀fstenv
?对于以下流:
\xf2\x66\x0f\x12\x00
GCC
和objdump
输出data16 movddup xmm0,QWORD PTR [eax]
所以他们以特定的顺序排列前缀,因此
\x66
在此之前被解释\xf2
,所以他们仍然使用读取的最后一个前缀\xf2
来确定指令movddup
。那么他们是在这里使用前缀的这种排列逻辑还是他们错了?Capstone
另一方面输出movlpd xmm0, qword ptr [eax]
所以他们没有以任何顺序排列前缀,他们只是读取最后一个前缀
\x66
来确定movlpd
在这种情况下看起来比什么GCC
和objdump
正在做的更合乎逻辑的指令。
cpu实际上是如何解释这些流的?
解决方案
可以相对容易地测试您的 CPU 实际解释这些流的方式。
对于第一个流,您可以使用我的工具nanoBench。你可以使用命令
sudo ./nanoBench.sh -asm_init "mov RAX, R14" -asm ".byte 0x9b, 0x9b, 0xd9, 0x30"
.
此命令首先设置RAX
为有效的内存地址,然后多次运行您的流。在我的 Core i7-8700K 上,我得到以下输出(用于固定功能性能计数器):
Instructions retired: 3.00
Core cycles: 73.00
Reference cycles: 62.70
我们可以看到 CPU 执行了三个指令,所以Capstone
看起来是正确的。
您可以使用 nanoBench 的调试模式分析第二个流:
sudo ./nanoBench.sh -unroll 1 -asm "mov RAX, R14; mov qword ptr [RAX], 1234; .byte 0xf2, 0x66, 0x0f, 0x12, 0x00" -debug
.
这将 - 在内部gdb
- 首先执行asm
代码,然后生成断点陷阱。我们现在可以查看 XMM0 寄存器的当前值:
(gdb) p $xmm0.v2_int64
$1 = {1234, 1234}
所以 XMM0 的高四字和低四字现在与地址 RAX 处的内存具有相同的值,这表明 CPU 执行了movddup
指令。
您也可以在不使用 nanoBench 的情况下分析第二个流。为此,您可以将以下汇编代码保存在一个文件中asm.s
。
.intel_syntax noprefix
.global _start
_start:
mov RAX, RSP
mov qword ptr [RAX], 1234
.byte 0xf2, 0x66, 0x0f, 0x12, 0x00
int 0x03 /* breakpoint trap */
然后,您可以使用
as asm.s -o asm.o
ld -s asm.o -o asm
现在您可以使用 gdb 对其进行分析gdb ./asm
:
(gdb) r
Program received signal SIGTRAP, Trace/breakpoint trap.
0x0000000000400088 in ?? ()
(gdb) p $xmm0.v2_int64
$2 = {1234, 1234}
推荐阅读
- javascript - 数据表 - 同一页面上的多个表,但只有一个附加按钮
- reactjs - 我想将此组件拆分为由容器呈现的组件
- docker - 通过 GitLab CI/CD 将 Docker 容器部署到 EC2 时出错:加载 pubkey“/root/.ssh/id_rsa”:格式无效
- vue.js - Vue/Vuex 动态组件不变
- ios - 如何在没有 NSFetchedResultsControllerDelegate 的情况下获取结果?
- jupyter-notebook - 通过 API 运行 Azure Notebook(外部)
- json - 如何从数组中获取 JSON 对象的值
- eclipse - 如何在 Eclipse 插件中从控制台捕获鼠标单击事件
- php - 如何在mysql中插入多行?
- python-3.x - Python 3:如何跟踪日期演变