Bochs源码分析 - 10: BX_NEXT_INSTR宏指令修改的错误

本文介绍了在分析Bochs源码时遇到的BX_NEXT_INSTR宏导致虚拟机无法正常运行的问题。尝试通过文本对比工具分析失败后,从源代码中找到解决方案,发现BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS宏影响了CPU执行路径。将该宏设为0后,问题得到解决。总结强调在修改源码前应充分阅读官方文档和代码,因为可能已有现成解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

        还记得我们在八篇文章中为了禁止CPU递归执行指令而取消的BX_NEXT_INSTR宏嚒,当时分析没有问题,但事后发现虚拟机跑不起来,其效果与日志如下:

 解决方案一(失败)

        我们先尝试着对比和正常的Bochs相比流程上存在哪些错误,我们用vscode的文本对比工具来进行对比,效果如下。经过仔细分析,其配置执行的流程已经被打乱,想要通过这种途径来分析代码似乎很困难。

 解决方案二(成功)

        我们只能从源代码中找答案,来看BX_NEXT_INSTR宏相关的上下文,发现其是一个 #IF..#ELSE..#ENDIF 这种数据结构。

#if BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS

...
#define BX_NEXT_INSTR(i) {                             \
  BX_COMMIT_INSTRUCTION(i);                            \
  if (BX_CPU_THIS_PTR async_event) return;             \
  ++i;                                                 \
  BX_EXECUTE_INSTRUCTION(i);                           \
}

#else
#define BX_NEXT_TRACE(i) { return; }
#define BX_NEXT_INSTR(i) { return; }
#define BX_LINK_TRACE(i) { return; }

#define BX_SYNC_TIME_IF_SINGLE_PROCESSOR(allowed_delta) \
  if (BX_SMP_PROCESSORS == 1) BX_TICK1()

#endif

        其实 BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS 这个宏,我们在第四篇编译调试模式时已经接触这个宏了。这个宏的意思从现在看,可以理解为:递归处理来提高CPU的处理速度。

        我们在config.h文件中将这个宏设置为0,再重新编译,回看cpu.cc文件中的cpu执行路径,发现已经有些变化,走的是另一个版本。可以看到存在 "BX_DEBUGGER","BX_GDBSTUB" 这个宏,其是专门为调试器实现的,我们不需要自然不用处理。

    for(;;) {

#if BX_DEBUGGER
      if (BX_CPU_THIS_PTR trace)
        debug_disasm_instruction(BX_CPU_THIS_PTR prev_rip);
#endif

      // want to allow changing of the instruction inside instrumentation callback
      BX_INSTR_BEFORE_EXECUTION(BX_CPU_ID, i);
      RIP += i->ilen();
      BX_CPU_CALL_METHOD(i->execute1, (i)); // might iterate repeat instruction
      BX_CPU_THIS_PTR prev_rip = RIP; // commit new RIP
      BX_INSTR_AFTER_EXECUTION(BX_CPU_ID, i);
      BX_CPU_THIS_PTR icount++;

      BX_SYNC_TIME_IF_SINGLE_PROCESSOR(0);

      // note instructions generating exceptions never reach this point
#if BX_DEBUGGER || BX_GDBSTUB
      if (dbg_instruction_epilog()) return;
#endif

      if (BX_CPU_THIS_PTR async_event) break;

      if (++i == last) {
        entry = getICacheEntry();
        i = entry->i;
        last = i + (entry->tlen);
      }
    }

总结

        在分析cpu时,我们一直苦恼于cpu对于递归的指令运行而无法很好的定位,然后自作聪明地想出了这个替换方案,然后在之后的运行中发现了问题,最后阅读源码发现bochs已经给出了一种很好的解决方案。

        这教会了我们一个道理:遇到问题想要自己动手改源代码之前,先好好看看官方文档和代码,可能人家已经提供了一种解决办法!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值