问题标签 [self-modifying]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
language-agnostic - 自修改代码?
我想做以下事情。我已经在我的程序中声明了一个结构,并且在程序执行时的运行时,如果有用户输入,我应该能够在我的代码中创建另一个新结构/编辑该结构。我们怎么能做到这一点?这就是“自我修改代码”吗?请澄清。请举一些例子。谢谢
让我想一下我想做什么,我有一个名为“student”的“结构/类”,其中包含“int roll_no”和“int reg_no”等变量。如果用户希望在运行时添加一个像“char name”这样的新变量,该怎么做?
c++ - 如何在 C++ 自修改汇编代码中内联?
我将如何在 C++ 函数中内联它。
我会怎么放
DB B8
DB 00
错误 C2400:“操作码”中的内联汇编语法错误; 发现执行 cl.exe的“常量”错误。
我认为我不能将其放在该.data
部分中,我已经阅读了我所能做的所有事情来包含这样的字节。
assembly - 处理器是否将数据从“L1 代码”缓存切换到“L1 数据”缓存?
我想知道,微处理器(比如说在长模式下的 SandyBridge 架构上)如何将数据从“L1 代码”切换到“L1 数据”缓存,反之亦然?假设一个页面用于数据存储,因此它被缓存在 L1 缓存中。然后,在 OS 执行过程中,指令指针跳转(发出 JMP 指令)到当前缓存在 L1 数据缓存中的内存位置。处理器是否将数据从 L1 数据迁移到 L1 代码缓存?当数据管理指令在存储在 L1 代码缓存中的地址上发出时,同样的问题(即意味着该地址变得适合数据存储,而不是代码执行) 处理器如何处理这些问题?
我问这个是因为我正在研究自我修改代码,如果您有任何其他信息可以阅读有关代码缓存的详细信息,请发布链接/参考。
android - 修改 NDK 并生成新的实验版本包
我正在尝试修改 NDK 并使用文档“android-ndk-r6\docs\DEVELOPMENT.html”生成新的实验性发布包,但在执行脚本 $NDK/build/tools/rebuild-all-prebuilt 后出现以下错误.sh --toolchain-pkg=:
错误:源目录不支持这些 ARCH:arm。. . 错误:无效的 sysroot:/tmp/ndk-Administrator/build/platforms/android-9/arch-arm
使用 --sysroot= 表示一个有效的。
所以请指导我如何解决这个问题
assembly - Homoiconic 和“不受限制”的自我修改代码 + lisp 真的是自我修改吗?
我承认我对 Lisp 的了解非常少。但是我对这门语言非常感兴趣,并计划在不久的将来开始认真学习它。我对这些问题的理解无疑是有缺陷的,所以如果我说了什么明显错误的话,请评论和纠正我,而不是投反对票。
真正的同音和自修改语言
我正在寻找支持 Homoiconicity(代码与数据具有相同的表示形式)和无限制的自我修改(无限制意味着您可以更改正在运行的代码的各个方面,而不仅仅是发出新代码或更改函数指针/代表。)
到目前为止,我发现只有三个例子符合这个标准:
- 机器码。Homoiconic 因为一切都是数字。可不受限制地修改,因为它包含指针,可用于操作任何内存地址,无论该地址是否包含代码或数据。
- 马尔堡。与机器代码相同的推理。每条指令在执行后都会自我修改
- 脱氧核糖核酸。不是编程语言,但仍然很有趣。它不像机器代码那样自我修改;实际指令+数据被修改到位的地方。然而,它是自我复制的,可以根据之前的状态变异/进化(辐射等副作用时不时地把它搞砸)。无论如何,这只是一种间接的自我修改方式。简而言之,DNA可以自我修改,但它是通过在其整体中复制自身以及相关突变来实现的。DNA 的物理串是“不可变的”。
为什么 Lisp 不在此列表中
Lisp 不在该列表中,因为在我看来 Lisp几乎是同音异形的,并且只支持受限的自我修改。你可以做类似的事情
这将做同样的事情
在第一个版本中(+ 1 2 3)
是原始代码,而在第二个版本中是数据。通过假设这个陈述的真实性,可以说 Lisp 甚至不是 homiconic。代码具有与数据相同的表示形式,因为它们都是列表/树/S 表达式。但是,您必须明确标记这些列表/树/S 表达式中的哪些是代码,哪些是对我来说是数据,这一事实似乎表明 Lisp 毕竟不是 homiconic。这些表示非常相似,但它们在微小的细节上有所不同,您必须实际说明您是在处理代码还是数据。这绝不是一件坏事(事实上其他任何事情都是疯狂的),但它突出了 Lisp 和机器代码之间的区别。在机器代码中,您不必明确标记哪些数字是指令,哪些是指针,哪些是数据。
这是反对不受限制的自我修改的更有力的案例。当然,您可以获取代表一些代码的列表并对其进行操作。例如改变
到
然后你运行它eval
。但是当你这样做时,你只是在编译一些代码并运行它。您不是在修改现有代码,您只是在发布和运行新代码。C# 可以使用表达式树做同样的事情,即使格式不太方便(这是由于 C# 代码对其 AST 具有不同的表示形式,而不是 Lisp,它是它自己的 AST)。您是否真的可以获取整个源文件并在整个源文件运行时开始修改它,对源文件所做的更改会对程序行为产生实时影响?
除非有某种方法可以做到这一点,否则 Lisp 既不是 homiconic 也不是自我修改的。(为了推迟对定义的争论,Lisp 不像机器代码那样同音或自我修改。)
使 Lisp Homoiconic/无限制地自我修改的方法
我可以看到 3 种潜在的方法来使 Lisp 像机器代码一样具有同义性/可自我修改。
- 非冯诺依曼架构。如果有人可以发明一些惊人的假设机器,其中程序的最低级别表示是可以直接执行的 AST(无需进一步编译)。在这样的机器上,AST 既代表可执行指令,也代表数据。不幸的是,问题还没有解决,因为 AST 仍然必须是代码或数据。eval 函数的出现不会改变这一点。在机器代码中,您可以根据需要在代码和数据之间来回切换。而使用 eval 和 Lisp 后,一旦您将某个列表从数据“评估”到代码并执行了它,就无法再次将该列表作为数据取回。实际上,该列表已永远消失,并已被其价值所取代。我们会遗漏一些关键的东西,这恰好是指针。
- 列出标签。如果要求每个列表也具有唯一标签,则可以通过对具有给定标签的列表运行函数来进行间接自我修改。结合延续,这最终将允许在与机器代码相同的意义上自我修改代码。标签等同于机器代码内存地址。例如,考虑一个 Lisp 程序,其中 AST 的顶部节点具有标签“main”。然后,在 main 中,您可以执行一个函数,该函数接受一个标签、一个整数、一个原子,并将原子复制到列表中,其标签与提供给函数的标签相匹配,位于整数指定的索引处。然后只需在 main 上调用当前的继续。你去,自我修改代码。
- Lisp 宏。我没有花时间去理解 Lisp 宏,它们实际上可能完全符合我的想法。
第 1 点与第 2 点相结合将产生一个完全自我修改的 Lisp。前提是可以生产所描述的神奇的 Lisp 机器。2. 单独可以产生一个自我修改的 Lisp,但是在冯诺依曼架构上的实现可能非常低效。
问题
- 除了机器码、dna 和 malbolge 之外,还有什么语言可以进行完全的自我修改并且是同音的?
- (如果您在上面的文字中做了一个 tl;dr,请不要费心回答)。lisp 真的是谐音+自我修改吗?如果你这么说,你能准确引用我的论点中我误入歧途的地方吗?
附录
具有不受限制的自我修改但没有同音性的语言
- 集会。该代码使用单词而不是数字,因此失去了同义性,但它仍然具有指针,它保留了对内存的完全控制并允许不受限制的自我修改。
- 任何使用原始指针的语言。例如 C/C++/Objective C。与 Assembly 相同的参数
- 包含虚拟指针的 JIT 语言。例如在不安全的上下文中运行的 C#/.net。与大会相同的论点。
其他可能相关/有趣的概念和语言:Lisp、Ruby、Snobol、Forth 和它的编译时元编程、Smalltalk 和它的反射、无类型的 lambda 演算及其属性,即一切都是函数(这意味着假设我们可以发明一台直接执行 lambda 演算的机器,lambda 演算将是同形的,而 Von Neumann 机器代码在该机器上运行时不会。[并且 Godels theorem 将是可执行的。哈哈,可怕的想法:P])
self-modifying - 自修改代码的用例?
在冯诺依曼架构上,程序和数据都存储在内存中,因此程序可以自行修改。这对程序员有用吗?你能举一些例子吗?
c++ - 在 C++ 中修改后修复文件权限?
我将我的数据保存在程序的可执行文件中。我将它复制到一个临时文件,覆盖以“魔术字符串”开头的部分并将其重命名为原始文件。我知道这是一个坏主意,但我这样做只是为了试验。
到目前为止,我已经完成了所有工作,除了每次替换文件时我都必须重新启用“允许作为可执行文件运行”。有什么方法可以解决这个问题?
附加信息:我使用linux。
c - 自修改代码,堆中复制/跳转失败
首先我很抱歉这篇文章的长度,但我想清楚地解释这个问题。
我尝试用 C 编写一种小型的自我修改程序,但我遇到了一些麻烦,我不知道究竟是为什么。
平台是: Ubuntu/Linux 2.6.32-40 x86_64,prog 基于 x86 arch,gcc (Ubuntu 4.4.3-4ubuntu5.1) 4.4.3,GNU ld (GNU Binutils for Ubuntu) 2.20.1-system.20100303
该程序的目的是创建一个读/写/执行内存块(使用memalign(3)和mprotect(2)),在这块内存中复制一个名为p()
(在.text
段中定义)的小函数,然后执行通过指针复制函数。该p()
函数仅使用显示一条消息printf(puts)
。
为了获取p()
(复制它)的代码的起始地址和结束地址,我使用了函数本身的地址和在indummy()
之后创建的函数的地址。p()
.text
块内存创建和复制已成功完成,但是当块中的代码运行时会发生段错误。通过使用gdb
很明显,我们输入了块的代码(复制的函数的主体),但是对printf 的调用失败了。反汇编p()
块中的函数和代码时,我发现“调用”中使用的地址不一样。
而且我不知道为什么地址不正确,复制代码时会显示它,这与我反汇编p()
函数时objdump(或gdb)给我的一样。
创建二进制文件是-static
为了避免. 在 上运行代码似乎不是问题,因为复制函数的开头已执行(检查下)。got/plt
ld.so
heap
gdb
程序的简化 src :
p()
反汇编的函数objdump(1)
:
当程序在 gdb(1) 下运行时,复制的代码与上面提供的 objdump(1) 相同(十六进制值):
如果我们查看 main ,我们接下来会进入块:
但是当 p() 和 chunk 被反汇编时,我们call 0x80d2c90
在内存块中有 a 而不是call 0x8048f50 <puts>
p() 函数中的 like 吗?由于这个原因显示的地址不一样。
检查内存时,代码似乎相同。在这一点上我不明白发生了什么,有什么问题?gdb的解释失败,代码副本还是什么?
如果设置了断点,则在内存块中继续执行:
因此,此时程序要么像那样运行并且发生段错误,要么 $eip 被更改并且程序结束而没有错误。
我不明白发生了什么,什么失败了。代码的副本似乎还可以,也可以跳转到内存块中,那么为什么(调用的)地址不好?
感谢您的回答和您的时间
ollydbg - 反汇编自修改代码
我一直在想——如何反汇编自修改二进制文件?我猜您不能使用 olly 或 IDA,因为它们是静态反汇编程序,对吗?如果你跳到指令的中间,反汇编程序会发生什么?以及如何分析变质引擎?
x86 - TARGET_HAS_PRECISE_SMC 是什么意思?
我只看到 x86 定义了 TARGET_HAS_PRECISE_SMC (target-i386/cpu.h),评论说,
我想知道它的含义并想了解更多信息,但谷歌搜索无济于事。你介意对此有所了解吗?谢谢。