网上很少有示例演示如何编写自修改代码。但它们只是示例。我想知道是否有任何真正的应用程序正在自我修改代码。谢谢!
5 回答
我可以参考其他架构吗?因为,当您使用较弱的系统(例如嵌入式应用程序)时,通常会使用 SMC,因为可供程序运行的 RAM 数量有限。
此外,维基百科有一个相当不错的列表。
“自我修改代码”也可以指 Java 中的字节码修改。这被许多框架使用,如 Guice、JPA、EJB 和 Web 容器以及几乎所有 AOP(面向方面编程)框架。基本上,它们会在 JVM 加载和执行字节码之前对其进行修改。所有这些框架都试图向类添加行为,而无需手动编写横切关注点。事务控制、依赖注入、范围或上下文注入是通常的嫌疑人。
我知道一个包含自我修改代码的程序(作为保护方案工作),如果输入正确的密码,它的作用是自行解密,并且解密的代码在将打开的文件保存到磁盘方面起着重要作用,这个程序被称为'WinHEX'.. 你可以在调用虚拟保护的正上方找到 SMC 代码,如果输入正确的密码,程序会调用 write process memory api 来解密该部分,并最终将文件保存到磁盘。
动态语言运行时 (DLR) 使用自修改代码来优化给定呼叫站点的常见类型。
假设您正在.NET 之上编写一种动态类型语言,并且您的语言中的源代码如下:
x + y
现在,在静态类型语言中,x
and的类型y
可以在编译时确定——比如x
andy
是int
s,然后x + y
将使用 IL“add”指令。
但是在动态类型语言中,这个分辨率每次都可能不同。下一次,x
并且y
可能是字符串,在这种情况下,此调用站点的值解析将使用 String.Concat。但是解决使用哪个 IL 的成本可能非常高。事实上,如果在调用站点的第一次命中中x
和y
是一对int
s,那么在这个调用站点上的连续命中很可能也是一对int
s。
因此 DLR 迭代如下:调用站点的编译代码如下所示:
return site.Update(site, x, y);
第一次传入给定的一组类型时——比如说,一对int
s,Update 方法转向语言实现来决定哪个方法/指令应该与一对int
s 和 a一起使用+
。然后将这些规则重新编译到调用站点中;生成的编译代码如下所示:
if (x is int x1 && y is int y1) { return x1 + y1; }
return site.Update(site, x, y);
连续调用成对的int
s 使编译后的代码保持不变。
如果遇到新的类型对,代码会自行重写为如下内容:
if (x is int x1 && y is int y1) { return x1 + y1; }
if (x is string x2 && y is string y2) { return String.Concat(x2, y2); }
return site.Update(site, x, y);
有关其工作原理的更多信息,请参阅Jim Hugunin 在 PDC 2008 上关于动态语言的演讲以及DLR 项目中的DLR 设计文档。