You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

寻求X86_64(amd64)无效二进制指令序列的高效查找方案及解码语法

如何系统推导AMD64未使用的指令序列并添加自定义指令到gem5

核心需求

我想要在X86_64(amd64)架构中添加自定义指令,生成包含这些指令的二进制文件后在gem5模拟器运行。目前仅能获取单字节未使用操作码列表,需要AMD64完整的解码语法,以此系统推导更长的无效二进制指令序列,替代当前的暴力测试方法。

现有暴力测试方案

当前通过C程序嵌入汇编字节序列,编译后用objdump标记的(bad)字段判断无效指令:

测试代码

int main()
{
        asm volatile(".byte 0x06" ::: "memory");
        asm volatile(".byte 0x07" ::: "memory");
        asm volatile(".byte 0x0E" ::: "memory");
        asm volatile(".byte 0x16" ::: "memory");
        asm volatile(".byte 0x17" ::: "memory");
        asm volatile(".byte 0x1E" ::: "memory");
        asm volatile(".byte 0x1F" ::: "memory");
        asm volatile(".byte 0x27" ::: "memory");
        asm volatile(".byte 0x2F" ::: "memory");
        asm volatile(".byte 0x37" ::: "memory");
        asm volatile(".byte 0x3F" ::: "memory");
        asm volatile(".byte 0x60" ::: "memory");
        asm volatile(".byte 0x61" ::: "memory");
        asm volatile(".byte 0x62" ::: "memory");
        asm volatile(".byte 0x82" ::: "memory");
        asm volatile(".byte 0x9A" ::: "memory");
        asm volatile(".byte 0xC4" ::: "memory");
        asm volatile(".byte 0xC5" ::: "memory");
        asm volatile(".byte 0xD4" ::: "memory");
        asm volatile(".byte 0xD5" ::: "memory");
        asm volatile(".byte 0xD6" ::: "memory");
        asm volatile(".byte 0xEA" ::: "memory");
        asm volatile(".byte 0xC5, 0x00, 0x00" ::: "memory");
        asm volatile(".byte 0xC5, 0x00, 0x01" ::: "memory");
        asm volatile(".byte 0xC5, 0x00, 0x02" ::: "memory");
        asm volatile(".byte 0xC5, 0x00, 0x03" ::: "memory");
        asm volatile(".byte 0xC5, 0x00, 0x04" ::: "memory");
        asm volatile(".byte 0xC5, 0x00, 0x05" ::: "memory");
        asm volatile(".byte 0xC5, 0x00, 0x06" ::: "memory");
        asm volatile(".byte 0xC5, 0x00, 0x07" ::: "memory");
        asm volatile(".byte 0xC5, 0x00, 0x08" ::: "memory");
        asm volatile(".byte 0xC5, 0x00, 0x09" ::: "memory");
        asm volatile(".byte 0xC5, 0x00, 0x0A" ::: "memory");
        asm volatile(".byte 0xC5, 0x00, 0x0B" ::: "memory");
        asm volatile(".byte 0xC5, 0x00, 0x0C" ::: "memory");
        asm volatile(".byte 0xC5, 0x00, 0x0D" ::: "memory");
        asm volatile(".byte 0xC5, 0x00, 0x0E" ::: "memory");
        asm volatile(".byte 0xC5, 0x00, 0x0F" ::: "memory");
        asm volatile(".byte 0xC5, 0x00, 0x10" ::: "memory");
        asm volatile(".byte 0xC5, 0x00, 0x11" ::: "memory");
        asm volatile(".byte 0xC5, 0x00, 0x13" ::: "memory");
        asm volatile(".byte 0xC5, 0x00, 0x17" ::: "memory");
        asm volatile(".byte 0xC5, 0x00, 0x18" ::: "memory");
        asm volatile(".byte 0xC5, 0x00, 0x19" ::: "memory");
        asm volatile(".byte 0xC5, 0x00, 0x1A" ::: "memory");
        asm volatile(".byte 0xC5, 0x00, 0x1B" ::: "memory");
        asm volatile(".byte 0xC5, 0x00, 0x1C" ::: "memory");
        asm volatile(".byte 0xC5, 0x00, 0x1D" ::: "memory");
        asm volatile(".byte 0xC5, 0x00, 0x1E" ::: "memory");
        asm volatile(".byte 0xC5, 0x00, 0x1F" ::: "memory");
        asm volatile(".byte 0xC5, 0x00, 0x01" ::: "memory");

        return 0;
} 

测试命令

gcc main.c && objdump -D -j .text a.out

示例输出(关键片段)

0000000000001119 <main>:
    1119:   55                      push   %rbp
    111a:   48 89 e5                mov    %rsp,%rbp
    111d:   06                      (bad)
    111e:   07                      (bad)
    111f:   0e                      (bad)
    1120:   16                      (bad)
    1121:   17                      (bad)
    1122:   1e                      (bad)
    1123:   1f                      (bad)
    1124:   27                      (bad)
    1125:   2f                      (bad)
    1126:   37                      (bad)
    1127:   3f                      (bad)
    1128:   60                      (bad)
    1129:   61                      (bad)
    112a:   62 82                   (bad)
    112c:   9a                      (bad)
    112d:   c4                      (bad)
    112e:   c5 d4 d5                (bad)
    1131:   d6                      (bad)
    1132:   ea                      (bad)
    1133:   c5 00 00                (bad)
    1136:   c5 00 01                (bad)
    1139:   c5 00 02                (bad)
    113c:   c5 00 03                (bad)
    113f:   c5 00 04                (bad)
    1142:   c5 00 05                (bad)
    1145:   c5 00 06                (bad)
    1148:   c5 00 07                (bad)
    114b:   c5 00 08                (bad)
    114e:   c5 00 09                (bad)
    1151:   c5 00 0a                (bad)
    1154:   c5 00 0b                (bad)
    1157:   c5 00 0c                (bad)
    115a:   c5 00 0d                (bad)
    115d:   c5 00 0e                (bad)
    1160:   c5 00 0f                (bad)
    1163:   c5 00 10                (bad)
    1166:   c5 00 11                (bad)
    1169:   c5 00 13                (bad)
    116c:   c5 00 17                (bad)
    116f:   c5 00 18                (bad)
    1172:   c5 00 19                (bad)
    1175:   c5 00 1a                (bad)
    1178:   c5 00 1b                (bad)
    117b:   c5 00 1c                (bad)
    117e:   c5 00 1d                (bad)
    1181:   c5 00 1e                (bad)
    1184:   c5 00 1f                (bad)
    1187:   c5 00 01                (bad)
    118a:   b8 00 00 00 00          mov    $0x0,%eax
    118f:   5d                      pop    %rbp
    1190:   c3                      ret

解决方案

1. 获取AMD64解码语法资源

  • 官方架构手册:Intel和AMD的官方软件开发者手册第2卷(指令集参考)是最权威来源,详细定义了指令编码结构:前缀(REX/VEX/EVEX等)、主操作码(1-3字节)、ModRM/SIB字节、立即数的组合规则,以及每类指令的操作码映射范围。
  • 开源解码器实现:参考gem5自身的X86解码器代码(src/arch/x86/isa/decoder目录),或者udis86、capstone等开源项目的解码逻辑,这些代码直接实现了AMD64的解码规则,能清晰看到未定义的操作码组合。
  • 结构化编码文档:第三方整理的按前缀分类的操作码空间文档,可快速定位未被占用的编码区间。

2. 系统推导无效指令序列的方法

  • 编码结构排除法:
    1. 明确AMD64指令的基本结构:可选前缀 + 1-3字节主操作码 + 可选ModRM/SIB字节 + 可选偏移量/立即数。
    2. 按前缀类型(无前缀、0F双字节操作码、VEX前缀等),对照官方手册排除已定义的操作码范围,剩余区间即为潜在无效序列。比如VEX前缀的C5开头指令,后续操作码字节若不在官方定义列表中,就属于无效指令(如你测试的C5 00 xx系列)。
  • 自动化解码器验证:
    • 用capstone库编写脚本,批量测试指令序列的解码结果,返回“无效指令”的序列即可作为自定义指令编码,效率远高于手动暴力测试。
    • 在gem5中添加临时调试逻辑,让模拟器输出无法解码的指令序列,结合自定义需求筛选合适的编码。
  • 优先选择连续未占用区间:
    • 优先挑选连续未被使用的操作码块,而非零散字节,方便后续扩展自定义指令,也避免和现有指令冲突。比如某些VEX前缀下的操作码子空间完全未被使用,是最优选择。

内容的提问来源于stack exchange,提问作者Setu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 03:01:09