从 MCInsts 获取"actual"寄存器 (x86)
Getting "actual" registers from MCInsts (x86)
我使用llvm-mc的目的是制作一个相对智能的反汇编程序(识别和跟踪本地程序、轻松跟踪分支等),其中一部分是创建反汇编指令的字符串表示。
当我开始这项工作时,我希望我能够相对容易地识别MCInst
使用的寄存器和值,并自己制作出另一种可以轻松使用的表示。然而,经过一些调查,我意识到用指令的文本表示显示的操作数与MCInst
对象中实际存在的操作数之间的相关性相当低。以下是几个例子(英特尔语法):
- 将11587作为32位立即数移动到
eax
将使用MOV32ri
操作码完成。文本表示将是mov eax, 11587
。对应的MCInst
将有两个操作数,一个寄存器和一个立即数。这对我有用。这太棒了 - 将
11587
添加到eax
将使用ADD32ri
操作码来完成。文本表示将是add eax, 11587
。然而,这一次,对应的MCInst
有三个操作数:eax
在那里两次,立即数在最后。这不太好。我可以假设这是降低过程的产物,eax
的第一个实例是目标寄存器,第二个实例是源寄存器(尽管x86不区分两者),我可以绕过这一点 - 将32位
eip
相对值移动到eax
将使用MOV32ao32
操作码来完成。文本表示将是mov eax, dword ptr [11587]
。在这种情况下,MCInst
甚至没有eax
的操作数,只能根据操作码名称中的操作数类型推断。我也可以绕过这一点,但事情越来越不好看了,我只测试了x86支持的1300多条指令中的5-6条
显然,为了显示文本,我可以用MCInstPrinter
获得文本表示,但那里显示的内容和MCInst
所具有的内容之间的映射仍然很模糊。
有没有一种简单的方法来判断哪些操作数出现在指令的文本表示中?
添加三个参数听起来像是编译器构建者对"三个地址代码"的偏好正在渗透,因为在英特尔汇编程序中没有理由这样做。(您不能使用add指令将数据添加并存储到不同的寄存器中,但可以使用LEA)。
如果计算所有扩展(如SSE、FPU等),操作码会有数百个,更糟糕的是,由于寻址模式和前缀,操作码有多种变体。
NASM汇编程序在源代码中有一些表,如果您的llvm-mc系统不提供这些功能,您可以尝试挖掘这些表。
MC级别非常低,操作数布局取决于操作码。也就是说,有一些映射表可以告诉你哪里是什么。MCInstrDesc和MCOperandInfo将告诉您哪些操作数、源和目的地,它们是否是立即数、寄存器等,以及一组标志。
您还需要熟悉MCRegisterClass和MCRegisterInfo以及其他一些东西。这是一个复杂的界面,因为表示任意目标信息的任务很复杂。
我会先看一下各种基于MC的工具的代码。你不应该需要自己的代表,MC应该拥有你需要的一切。
- 本质:使用__128寄存器
- 将寄存器设计成可由C和C++访问的外设的最佳实践
- 在模拟器中使用并集来模拟CPU寄存器有多合适
- 使用英特尔 PIN 修改寄存器
- AVX 指令中寄存器和指针之间的客观差异
- 如何确定我的处理器有多少个 AVX 寄存器?
- 除非使用某些寄存器,否则函数挂钩会崩溃
- 寄存器上的管道计算
- 其中关于内存和寄存器的左值和右值
- 有没有办法强制C++编译器将变量存储在寄存器中?
- "变量":函数中函数作用域不允许初始化的自动或寄存器变量'naked'
- Atmel Studio:返回一个包含数组的寄存器
- 使用 googletest 测试嵌入式C++代码时处理外设寄存器的重复符号
- 移位寄存器74HC595输出电流
- 超过255的Modbus寄存器无法访问SimpleModbus
- 如何在程序集函数中将元素数组作为参数传递时转发 ARM 寄存器的地址指针
- X86-64上的C :何时通过结构/类在寄存器中返回
- 在英特尔x86体系结构上使用非AVX指令修改xmm整数寄存器值
- 从 MCInsts 获取"actual"寄存器 (x86)
- 按照每个通用寄存器的用途对 x86 程序集进行编码是必要还是更容易