- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我继承了用8051汇编语言编写的10K行程序,该程序需要进行一些更改。不幸的是,它是用意大利面条代码的最佳传统编写的。该程序(作为单个文件编写)是CALL和LJMP语句(总共约1200个)的迷宫,如果可以将它们完全识别为子例程,则它们具有多个入口和/或出口点。所有变量都是全局变量。有评论;有些是正确的。没有现有的测试,也没有用于重构的预算。
该应用程序的一些背景知识:该代码控制着目前在国际上部署的自动售货应用程序中的通信中心。它可以同时处理两个串行流(借助于单独的通信处理器),并且可以与多达四个不同的物理设备进行通信,每个物理设备都来自不同的供应商。其中一台设备的制造商最近进行了更改(“是的,我们进行了更改,但是软件完全相同!”),这导致某些系统配置不再起作用,并且不希望对其进行更改(无论它是什么)他们没有改变)。
该程序最初由另一家公司编写,然后转移给我的客户,然后在九年前由另一位顾问进行了修改。既没有原始公司,也没有顾问作为资源。
根据对其中一条串行总线上的通信量的分析,我提出了一种破解方法,该方法看起来很有效,但它很丑陋,无法解决根本原因。如果我对程序有更好的了解,我相信我可以解决实际的问题。在冻结代码之前,我还有大约一周的时间来支持月底发货日期。
最初的问题:我需要对程序有足够的了解,以进行更改而不会造成损坏。有没有人开发出处理此类混乱的技术?
我在这里看到了一些很棒的建议,但受时间限制。但是,将来我可能还有另一个机会来寻求一些更复杂的行动方案。
最佳答案
首先,我将尝试与那些最初开发该代码或至少在我之前维护过代码的人保持联系,希望能获得足够的信息以大致上了解该代码,以便您可以开始在其中添加有用的注释。它。
也许您甚至可以让某人描述代码中最重要的API(包括其签名,返回值和用途)。如果全局状态是通过函数修改的,则还应该使其明确。同样,开始区分功能和过程以及输入/输出寄存器。
您应该向您的雇主清楚地表明,需要这些信息,如果他们不相信您,让他们在您描述应该做的事情和必须做的事情的同时坐在本代码前面与您坐下来它(逆向工程)。在这种情况下,拥有具有计算和编程背景的雇主实际上会有所帮助!
如果您的雇主没有这样的技术背景,请他带另一个程序员/同事向他解释您的步骤,这样做实际上会告诉他您对此很认真和诚实,因为这是一个真实的问题-不仅仅是从您的角度(确保有了解此“项目”的同事)。
如果可行且可行的话,我也要非常清楚地指出,与前开发人员/维护人员签约(或至少联系)(如果他们不再为您的公司工作,则)以帮助记录此代码将是一个先决条件。 -在短时间内切实改进代码并确保将来可以更轻松地维护代码的必要条件。
强调整个情况是由于先前的软件开发过程中的缺陷,这些步骤将有助于改进代码库。因此,当前形式的代码库是一个日益严重的问题,现在为解决此问题所做的一切都是对未来的投资。
这本身对帮助他们评估和了解您的情况也很重要:要做您现在应该做的事情并非易事,他们应该知道这一点-如果只是为了直指他们的期望(例如,关于截止日期和复杂性)任务)。
另外,个人而言,我将开始为我已经足够了解的那些部分添加单元测试,以便我可以慢慢地开始重构/重写一些代码。
换句话说,好的文档和源代码注释是一回事,而拥有全面的测试套件则是另一回事,在没有任何成熟的测试关键功能的方法的情况下,没有人可以期望修改任何不熟悉的代码库。
假定代码为10K,我还将考虑将子例程分解为单独的文件,以使组件更易于识别,最好使用访问包装器而不是全局变量和直观的文件名。
此外,我将研究通过降低复杂性来进一步提高源代码可读性的步骤,使具有多个入口点的子例程(甚至可能具有不同的参数签名?)看起来像是不必要地混淆代码的可靠方法。
同样,巨大的子例程也可以重构为较小的子例程,以帮助提高可读性。
因此,我要做的第一件事就是确定使代码库变得非常复杂的那些事情,然后重新加工这些部分,例如,通过将具有多个入口点的巨大子例程拆分为不同的子例程彼此调用的子例程。
如果由于性能原因或调用开销而无法完成此操作,请改用宏。
另外,如果这是一个可行的选择,我会考虑使用更高级的语言来逐步重写部分代码,或者使用C的子集,或者至少通过大量使用汇编宏来帮助标准化代码。基础,也有助于定位潜在的错误。
如果使用C进行增量重写是可行的选择,那么一种可能的入门方式是将所有明显的函数转换为C函数,这些函数的主体是-从头开始-从汇编文件复制/粘贴的,因此最终得到C具有许多内联汇编的功能。
就我个人而言,我还将尝试在simulator/emulator中运行代码以轻松地逐步遍历代码,并希望开始了解最重要的构造块(在检查寄存器和堆栈使用情况的同时),应该使用具有内置调试器的良好的8051模拟器提供给您,如果您真的必须自己做的话。
这也将帮助您提出初始化序列和主循环结构以及一个调用图。
也许,您甚至可以找到一个很好的开源80851模拟器,可以轻松对其进行修改以自动提供完整的调用图,只需进行快速搜索,我就找到了gsim51,但是显然还有其他几种选择,还有各种专有的选择。
如果您遇到这种情况,我什至会考虑外包修改我的工具以简化使用此源代码的工作,即许多sourceforge项目接受捐款,也许您可以说服您的雇主赞助这样的修改。
如果不是经济上的话,也许是通过您提供相应的补丁程序呢?
如果您已经在使用专有产品,您甚至可以与该软件的制造商联系并详细说明您的要求,并询问他们是否愿意以这种方式改进该产品,或者是否至少可以公开一个界面以允许客户进行这样的自定义(某种形式的内部API甚至简单的粘合脚本)。
如果他们没有反应,请表明您的雇主已经考虑使用某种产品已有一段时间了,并且您是唯一坚持使用该特定产品的人... ;-)
如果软件需要特定的I / O硬件和外围设备,则您甚至可能希望研究编写相应的硬件仿真循环以在仿真器中运行该软件。
最终,我知道一个事实,那就是,无论我能喝多少加仑咖啡,我个人都会更喜欢自定义其他软件的过程来帮助我理解这样的意大利面条式代码怪兽,而不是手动单步执行代码并自己玩模拟器得到。
从一个开源8051仿真器中获得一个可用的调用图最多要花一个周末的时间(最多一次),因为这主要是指查找CALL操作码并记录其地址(位置和目标),以便将所有内容都丢弃到文件以供以后检查。
实际上,可以使用仿真器的内部结构也是进一步检查代码的一种好方法,例如,以便找到操作码的重复模式(例如20-50 +),这可能是独立函数/过程的因素,实际上帮助进一步减少代码库的大小和复杂性。
下一步可能是检查堆栈并注册使用情况。并确定所用功能参数的类型/大小及其值范围-这样您就可以构思相应的单元测试。
与手动完成所有这些工作相比,使用点/ graphviz之类的工具来可视化初始化序列和主循环本身的结构将是一种纯粹的乐趣。
而且,从长远来看,您最终将获得有用的数据和文档,它们可以作为更好的文档的基础。
关于assembly - 解开汇编语言意粉代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/983574/
我不确定 cbw命令实际上可以。我有一段代码: mov ax,0FF0h cbw idiv ah cbw后ax的值如何变化? 最佳答案 cbw指令将一个字节符号扩展为一个字。在这种情况下,它将采用
MIPS 架构中的.s 和.asm 有什么区别? 最佳答案 .s 和.asm 之间没有天生的区别 如果你愿意,你可以用 .s 命名文本文件,用 .asm 命名十六进制文件,但这只是为了让它们保持正直。
我正在业余时间学习汇编语言,以成为更好的开发人员。 我在概念层面上理解基于堆栈的机器和基于寄存器的机器之间的区别,但我想知道基于堆栈的机器实际上是如何实现的。如果是虚拟机,例如JVM 或 .NET,在
几周后我开始上大学(软件工程学位),并且知道我将在第一年学习的一个模块是“建筑基础”或类似的东西;基本上它是在学习“汇编”中的编程。 我想做一些背景学习,所以我为此做好了准备(我在其他一些单元上做了同
我是汇编语言的新手。我目前正在经历这个 Assembly Guide .我对 LEA 指令有疑问。我对LEA指令的理解是LEA用source operand的有效地址加载destination ope
x86 汇编中是否有模运算符或指令之类的东西? 最佳答案 如果您的模数/除数是一个已知常数,并且您关心性能,请参阅 this和 this .对于直到运行时才知道的循环不变值,乘法逆甚至是可能的,例如见
我是汇编语言的新手。我目前正在经历这个 Assembly Guide .我对 LEA 指令有疑问。我对LEA指令的理解是LEA用source operand的有效地址加载destination ope
我相信这对大多数人来说非常简单,但我对 x86 汇编语言不是很熟悉。我只是想自学。 我在 window 里。在我读到的任何地方,我都被告知要使用 INT 21返回操作系统。这退出了程序,但我收到一条错
我正在尝试输入一个字符串,然后查看该字符串中的最后一个值是否为 EOL 字符。我想我会使用读入的字符串的长度,然后将它添加到缓冲区的地址以找到最后一个元素。这似乎不起作用。 编辑:很抱歉我没有包含更多
; This program checks for even or odd parities inside of an array. Displays 1 if even or 0 if odd. I
我一直在努力掌握 x86 汇编语言,并且想知道是否有一个与 movl $1, %eax 等效的快速简短的语言。就在那时,我认为列出该语言中经常使用的习语可能是个好主意。 这可能包括首选使用 xorl
有人知道如何在 ARMv6 汇编语言中开始注释(例如“#”、“;”、“/”、“/*”)吗? 最佳答案 应该是“;”根据我在 wikipedia article: 上找到的一些示例代码 loop
; This program checks for even or odd parities inside of an array. Displays 1 if even or 0 if odd. I
我是一名利用业余时间学习汇编语言的大学生。我注意到虽然有像 add 和 mul 这样的指令,但算术运算符经常在指令中使用。例如: mov eax,[ebx+ecx] 它等价于以下吗? add ebx,
我真的是学习汇编语言的新手,并且刚刚开始研究汇编语言,所以我想知道也许有些人可以帮助我解决一个问题。我有一个作业,告诉我将汇编语言指令与C代码进行比较,并告诉我哪些C代码与汇编指令等效。所以这是组装说
假设我有以下代码: C++ 代码和内联汇编代码如下: 方程式: X=40+5 Y=3*12 ---> X=45 Y=36 测试 if x < y - print x+y else print x-y
我正在编写一个程序,其中的要求如下: 有一个名为 Name 的字符串变量,该变量设置为您的全名,包括空格。 只清除 AL 寄存器,不清除 EAX 寄存器的其余部分。 遍历 Name 变量中的每个字符。
我有一个任务,描述如下: - Reads printable characters (20h-7Fh) from the keyboard without echoing - Uppercase le
我正在查看 switch 语句的汇编语言代码。 我了解代码的工作原理以及情况。我的问题是如何决定案例名称? 下面是汇编语言代码,下面是我的解释。我基本上只需要使用跳转表并填写案例名称。 1 8
我是汇编语言新手,我想到了这个问题:构建代码、宏或过程哪个是更好的解决方案?虽然宏中包含的代码只是复制到所需的部分,并且允许执行代码而无需昂贵的跳转,但它确实添加了必须在程序执行时加载的额外指令。此外
我是一名优秀的程序员,十分优秀!