deo*_*deo 119 executable platform-agnostic cpu-architecture instructions self-modifying
你能想到运行时代码修改的任何合法(智能)用法(程序在运行时修改它自己的代码)吗?
现代操作系统似乎对执行此操作的程序不屑一顾,因为病毒已使用此技术来避免检测.
我能想到的是某种运行时优化,它可以通过在运行时知道某些在编译时无法知道的东西来删除或添加一些代码.
Mac*_*ser 117
有许多有效的代码修改案例.在运行时生成代码可用于:
有时代码在运行时被转换为代码(这称为动态二进制转换):
代码修改可用于解决指令集的限制:
更多代码修改案例:
tre*_*nki 35
这已经在计算机图形学中完成,特别是用于优化目的的软件渲染器.在运行时,检查许多参数的状态,并生成光栅化器代码的优化版本(可能消除许多条件),这允许人们更快地渲染图形基元,例如三角形.
flo*_*olo 23
一个有效的原因是因为asm指令集缺少一些必要的指令,你可以自己构建.示例:在x86上,无法为寄存器中的变量创建中断(例如,使用ax中的中断号进行中断).只允许编码到操作码中的常数.使用自修改代码,可以模拟此行为.
Ton*_*roy 17
有很多情况:
某些操作系统的安全模型意味着自修改代码无法在没有root/admin权限的情况下运行,这使得它对于通用目的而言不切实际.
来自维基百科:
在具有严格W ^ X安全性的操作系统下运行的应用软件不能在允许写入的页面中执行指令 - 仅允许操作系统本身向存储器写入指令并随后执行那些指令.
在这样的操作系统上,即使像Java VM这样的程序也需要root/admin权限来执行它们的JIT代码.(有关详细信息,请参阅http://en.wikipedia.org/wiki/W%5EX)
Joe*_*oeG 17
一些编译器过去常常将其用于静态变量初始化,从而避免了后续访问的条件成本.换句话说,它们通过在第一次执行时使用无操作覆盖该代码来实现"仅执行一次此代码".
很多年前我花了一个上午试图调试一些自修改代码,一条指令改变了下一条指令的目标地址,即我正在计算一个分支地址.它是用汇编语言编写的,当我一次完成一个指令时,它工作得很好.但是当我运行该程序时,它失败了.最后,我意识到机器正在从内存中取出2条指令(并且(因为指令在内存中布局),我正在修改的指令已被取出,因此机器正在执行指令的未修改(不正确)版本.当然,当我调试时,它一次只做一条指令.
我的观点是,自修改代码对于测试/调试来说非常讨厌,并且通常对机器的行为(无论是硬件还是虚拟)有隐藏的假设.此外,系统永远不会在(现在)多核机器上执行的各种线程/进程之间共享代码页.这会破坏虚拟内存等许多好处.它还会使在硬件级别完成的分支优化无效.
(注意 - 我没有将JIT包含在自修改代码的类别中.JIT正在从代码的一个表示转换为替代表示,它不是修改代码)
总而言之,这只是一个坏主意 - 真的很整洁,真的很模糊,但非常糟糕.
当然 - 如果你拥有8080和512字节的内存,你可能不得不求助于这种做法.
从操作系统内核的角度看,每个Just In Time Compiler和Linker Runtime都会执行程序文本自我修改.突出的例子是Google的V8 ECMA Script Interpreter.
小智 5
您知道旧的栗子,硬件和软件之间没有逻辑差异......也可以说代码和数据之间没有逻辑差异.
什么是自修改代码?将值放入执行流中的代码,以便可以将其解释为数据而不是命令.当然,功能语言中的理论观点确实没有区别.我在说e可以在命令式语言和编译器/解释器中以直截了当的方式做到这一点,而没有假设平等的地位.
我所指的是实际意义上的数据可以改变程序执行路径(在某种意义上,这是非常明显的).我正在考虑像编译器编译器这样的东西,它创建一个表(数据数组),在解析,遍历状态(以及修改其他变量)时遍历,就像程序从命令移动到命令一样,修改过程中的变量.
因此,即使在编译器创建代码空间并引用完全独立的数据空间(堆)的通常情况下,仍然可以修改数据以显式更改执行路径.