ANSI C90环境下68HC11汇编Opcode错误捕获实现咨询
解决方案
1. 用Opcode属性结构体统一管理指令信息
先定义结构体存储每个Opcode的核心属性,彻底避免逐个编写重复逻辑:
typedef struct { unsigned char opcode; int operand_len; // 操作数占用字节数(0/1/2) const char *mnemo; // 指令助记符 } OpcodeEntry; // 示例:LD类Opcode列表(根据你的指令集补充完整) const OpcodeEntry ld_ops[] = { {0xB6, 2, "LDAA"}, // 扩展寻址,2字节操作数 {0x18, 1, "LDAA"}, // IND,Y寻址,1字节操作数 {0x96, 1, "LDAA"}, // 直接寻址,1字节操作数 // 其他LD类Opcode... }; const int ld_ops_count = sizeof(ld_ops) / sizeof(ld_ops[0]);
2. 构建合法Opcode的快速检测掩码
用256位掩码实现单字节是否为Opcode的快速判断,避免每次遍历全量Opcode数组:
unsigned char opcode_mask[32] = {0}; // 32*8=256位,对应0x00-0xFF // 初始化掩码:将所有合法Opcode对应的位设为1 void init_opcode_mask() { int i = 0; // 先处理LD类 while (i < ld_ops_count) { unsigned char oc = ld_ops[i].opcode; opcode_mask[oc / 8] |= (1 << (oc % 8)); i++; } // 再添加其他类Opcode... } // 判断字节是否为合法Opcode int is_valid_opcode(unsigned char byte) { return (opcode_mask[byte / 8] & (1 << (byte % 8))) != 0; }
3. 反汇编核心逻辑(含错误处理)
按以下流程处理内存字节,同时覆盖非法Opcode场景:
void disassemble(unsigned char *mem, int mem_len) { int ptr = 0; while (ptr < mem_len) { unsigned char current_oc = mem[ptr]; OpcodeEntry entry; int found = 0; int i = 0; // 查找当前Opcode对应的指令信息(C90用while代替for) while (i < ld_ops_count) { if (ld_ops[i].opcode == current_oc) { entry = ld_ops[i]; found = 1; break; } i++; } if (!found) { // 未知Opcode,标记错误并跳过 printf("(???)\n"); ptr++; continue; } // 检查操作数区域是否包含合法Opcode int invalid = 0; int op_ptr = 1; while (op_ptr <= entry.operand_len && ptr + op_ptr < mem_len) { if (is_valid_opcode(mem[ptr + op_ptr])) { invalid = 1; break; } op_ptr++; } if (invalid) { // 操作数区域出现Opcode,标记错误,跳转到该Opcode位置 printf("(???)\n"); ptr += op_ptr; // 直接跳转到第一个非法Opcode的位置 } else { // 正常反汇编指令 printf("%s ", entry.mnemo); if (entry.operand_len == 1) { printf("$%02X\n", mem[ptr + 1]); } else if (entry.operand_len == 2) { // 根据目标处理器字节序调整输出顺序(示例为大端) printf("$%02X%02X\n", mem[ptr + 1], mem[ptr + 2]); } else { printf("\n"); } ptr += 1 + entry.operand_len; } } }
4. 关键注意事项
- 避免遗漏合法Opcode:当检测到操作数区域出现合法Opcode时,直接跳转到该Opcode位置开始下一轮反汇编,不会遗漏如0x18这类合法指令。
- C90兼容性:所有循环用
while实现,结构体、数组定义完全符合C90标准,无语法兼容问题。 - 字节序适配:反汇编多字节操作数时,需根据目标处理器的字节序调整输出顺序(如Motorola 6800系列为大端,Intel x86为小端)。
- 扩展性:新增Opcode只需补充到
OpcodeEntry数组和掩码初始化逻辑中,无需修改核心反汇编代码。
针对你提到的具体问题的修复
- 0xB6非法场景:若0xB6后2字节内出现合法Opcode(如0x18),会直接标记为
(???),并跳转到0x18开始处理,不会将其当作操作数。 - 避免重复逻辑:通过Opcode数组和掩码统一处理所有指令的操作数检查,无需逐个编写错误处理代码。
- 修复
LDAA$A6FF错误:当0xB6后第一个字节是合法Opcode(如0xA6),会判定为非法指令,不会将后续字节当作操作数输出。
内容的提问来源于stack exchange,提问作者Perfect Paradox
相关产品推荐
相关产品推荐

