首先,我会尝试与那些最初开发代码或至少在我之前维护它的人取得联系,希望能获得足够的信息来对代码有一个基本的了解,这样你就可以开始添加有用的注释它。
也许您甚至可以让某人描述代码中最重要的 API(包括它们的签名、返回值和用途)。如果全局状态被函数修改,这也应该明确。同样,开始区分函数和过程,以及输入/输出寄存器。
您应该向您的雇主非常清楚地表明此信息是必需的,如果他们不相信您,请让他们在您描述您应该做什么以及您必须如何做的同时在此代码前与您坐下来它(逆向工程)。在这种情况下,拥有具有计算和编程背景的雇主实际上会有所帮助!
如果您的雇主没有这样的技术背景,请让他带另一位程序员/同事向他解释您的步骤,这样做实际上会向他表明您对此是认真和诚实的,因为这是一个真正的问题-不仅仅是从你的角度来看(确保有知道这个“项目”的同事)。
如果可用且可行,我也会非常清楚地表明,与以前的开发人员/维护人员(如果他们不再为您的公司工作,也就是说)签订合同(或至少联系)以帮助记录此代码将是一个预先- 在短时间内实际改进代码并确保将来可以更轻松地维护它的必要条件。
强调这整个情况是由于以前的软件开发过程中的缺陷造成的,这些步骤将有助于改进代码库。因此,当前形式的代码库是一个日益严重的问题,现在为解决这个问题所做的一切都是对未来的投资。
这本身对于帮助他们评估和理解你的情况也很重要:做你现在应该做的事情绝非易事,他们应该知道这件事——如果只是为了明确他们的期望(例如关于截止日期和复杂性)任务)。
另外,我个人会开始为那些我理解的部分添加单元测试,这样我就可以慢慢开始重构/重写一些代码。
换句话说,好的文档和源代码注释是一回事,但拥有一个全面的测试套件是另一回事,如果没有任何已建立的测试关键功能的方法,没有人可以实际期望修改不熟悉的代码库。
鉴于代码为 10K,我还将考虑将子例程分解为单独的文件以使组件更易于识别,最好使用访问包装器而不是全局变量以及直观的文件名。
此外,我会考虑通过降低复杂性来进一步提高源代码可读性的步骤,让子例程具有多个入口点(甚至可能是不同的参数签名?)看起来是一种不必要地混淆代码的可靠方法。
同样,巨大的子例程也可以重构为更小的子例程,以帮助提高可读性。
因此,我首先要做的事情之一是确定那些使深入了解代码库变得非常复杂的事情,然后重新处理这些部分,例如通过将具有多个入口点的巨大子例程拆分为不同的而是相互调用的子例程。如果由于性能原因或调用开销而无法做到这一点,请改用宏。
此外,如果这是一个可行的选择,我会考虑使用更高级的语言逐步重写部分代码,或者通过使用 C 的子集,或者至少通过相当多地使用汇编宏来帮助标准化代码基础,也有助于本地化潜在的错误。
如果在 C 中进行增量重写是一个可行的选择,那么一种可能的开始方法是将所有明显的函数转换为 C 函数,其主体在开始时是从汇编文件中复制/粘贴的,因此您最终会使用 C具有大量内联汇编的功能。
就个人而言,我也会尝试在模拟器/模拟器中运行代码以轻松单步执行代码并希望开始理解最重要的构建块(同时检查寄存器和堆栈的使用情况),应该是一个带有内置调试器的好的 8051 模拟器如果您确实必须自己做这件事,则可以使用。
这也将帮助您提出初始化序列和主循环结构以及调用图。
也许,您甚至可以找到一个很好的开源 80851 模拟器,它可以轻松修改以自动提供完整的调用图,只需快速搜索,我就找到了 gsim51,但显然还有其他几个选项,以及各种专有选项。
如果我处于你的情况,我什至会考虑将修改我的工具的工作外包以简化使用此源代码的工作,即许多 sourceforge 项目接受捐赠,也许你可以说服你的雇主赞助这样的修改。
如果不是经济上的,也许你提供相应的补丁?
如果您已经在使用专有产品,您甚至可以与该软件的制造商交谈并详细说明您的要求,并询问他们是否愿意以这种方式改进该产品,或者他们是否至少可以公开一个界面以允许客户进行此类定制(某种形式的内部 API,甚至可能是简单的胶水脚本)。
如果他们没有回应,请表明您的雇主已经考虑使用不同的产品一段时间了,并且您是唯一坚持使用该特定产品的人...... ;-)
如果软件需要特定的 I/O 硬件和外围设备,您甚至可能需要考虑编写相应的硬件仿真循环以在仿真器中运行该软件。
最终,我知道我个人更喜欢定制其他软件来帮助我理解这样一个意大利面条代码怪物的过程,而不是手动单步执行代码并自己玩模拟器,不管我能喝多少加仑咖啡得到。
从开源 8051 模拟器中获取可用的调用图应该不会比说一个周末(最多)花费更长的时间,因为这主要意味着寻找 CALL 操作码并记录它们的地址(位置和目标),以便将所有内容都转储到存档以备日后检查。
访问仿真器的内部实际上也是进一步检查代码的好方法,例如为了找到操作码的重复模式(比如 20-50+),这可能会被考虑到独立的函数/过程中,这实际上可能有助于进一步降低代码库的大小和复杂性。
下一步可能是检查堆栈和寄存器的使用情况。并确定使用的函数参数的类型/大小,以及它们的取值范围——以便您可以构思相应的单元测试。
使用 dot/graphviz 之类的工具来可视化初始化序列的结构和主循环本身,与手动完成所有这些工作相比,这将是一种纯粹的乐趣。
此外,您实际上最终会得到有用的数据和文档,从长远来看,这些数据和文档可以作为更好的文档的基础。