Assembly 组件级评估

Assembly 组件级评估,assembly,eval,Assembly,Eval,我开始学习最基本的汇编语言,我了解到编译后的代码进入一个名为code-segment的特殊段,这是一个写保护段(至少在现代体系结构中是这样) 但是一个问题突然出现了:在一些编程语言中(例如:EcmaScript、Python等),有一个神奇的eval()函数,它接受字符串,解析它,然后执行它 由于代码是在运行时(然后在填充代码段之后)进行计算的,并且代码段是写保护的,所以它执行什么样的魔法 我想它与JIT编译有关,但还没有关于它在低级别如何工作的线索。让我们以python为例 Python被解释

我开始学习最基本的汇编语言,我了解到编译后的代码进入一个名为
code-segment
的特殊段,这是一个写保护段(至少在现代体系结构中是这样)

但是一个问题突然出现了:在一些编程语言中(例如:EcmaScript、Python等),有一个神奇的
eval()
函数,它接受字符串,解析它,然后执行它

由于代码是在运行时(然后在填充代码段之后)进行计算的,并且代码段是写保护的,所以它执行什么样的魔法


我想它与JIT编译有关,但还没有关于它在低级别如何工作的线索。

让我们以python为例

Python被解释(除非使用支持pypi或JIT的引擎,但即使在那里,您也可以动态调用解释器)。运行时,程序始终可以访问python可执行文件中内置的解释器,该解释器在运行时正在运行(评估是运行时的一部分,这是后续的)

因此,
eval
仅使用内置解释器计算表达式

由于python意味着性能,因此在加载模块时,您的代码将转换为字节码以节省文本解析时间(例如Java在编译时这样做),但实际执行的机器指令包含在
python
可执行文件中(它解释字节码并执行适当的操作)或者加载了属于DLL的
.pyd
文件

JIT只是字节码之上的另一种优化:它在内存段中动态生成本机代码,但您无法轻松访问此段(就像在C中使用函数地址一样),因此从python程序内部破解此代码将非常困难

编译或编译语言(C,C++,艾达……)这是不可能的(至少不容易),这并不是因为代码段的写保护(这是不保证的),而是因为运行程序无法汇编/编译代码:它没有嵌入编译器/汇编程序。运行时(如果存在)是最小的,并且肯定不包含源代码评估

最简单的方法是用程序创建一个临时文件,从程序中调用编译器/汇编程序,并在单独的进程中执行它,或者动态加载DLL,但这并不简单


正如Frank所说的,另一种可能的方法是在程序中创建一个虚拟机,像真正的CPU那样评估机器代码指令(或者像编译器那样评估高级指令)。不用说,这不是一件小事,但一些已经存在的库(例如QEMU)可以做到这一点,即使有了现有的资料,实现起来也很不容易。

从不同的角度回答

“代码段”的不可写标志只是操作系统在加载可执行文件时所做的安排。在硬件级别上,也没有任何东西阻止操作系统准备可写+可执行的内存页,在写保护内存页中运行可执行文件只是一种方便的安全措施和错误预防。应用程序的创建者尊重这一点,不再使用可自我修改的代码(这是早期汇编编程的常见做法)。(除非他们为此目的从操作系统中分配额外内存,否则在那里写入并随后执行)

另外,整个“代码段”是高级抽象,CPU本身不知道类似的事情

(x86)CPU只有当前权限级别和虚拟内存映射,因此它访问的任何内存地址都将通过虚拟映射定义转换为物理内存地址,同时根据请求的操作检查内存“页面”(can读/can写)的权限

如果访问无效,它将陷入错误处理程序中,通常是操作系统提供的


无论应用程序在单独的内存页中加载代码和数据,或者甚至数据部分在可写和只读之间有很好的区别,都取决于操作系统和应用程序加载器通过CPU提供的内存映射的简单特权/标志机制来设置它。如果你有自己的操作系统,你也可以将整个内存映射到一个大的不受保护的块中,每个人都可以读+执行+写。

我不喜欢Python,但喜欢嵌入式系统。在PC中,我假设操作系统(Windows/Unix/Android/etc)将通过MMU(内存管理单元)物理内存区域保留给每个段,并为其分配访问权限。要动态加载一个可执行程序以在之后执行它,正如Python所做的那样,应该预先声明一个具有读/写/执行权限的段。默认情况下,Python应该这样做,但它不应该是“代码段”,正如您所说的,它是只读的。也就是说,并非所有的“程序代码”都指向同一段。 例如,在汇编代码中,可以确定在“段/节名”上声明代码/数据段的位置。链接器将采用与项目中包含的文件同名的段,以顺序方式连接具有相同名称的段,并将它们分配到“链接器指令文件”(有时是扩展名为“.ld”的文件)固定的地址。
不同的编译器对段有名称约定(典型的是“代码”、“数据”、“文本”、“bss”等)。每个人通常都有其读/写/执行访问权限的属性。

python被解释(除非使用pypi,但即使在那里,您也可以动态调用解释器)。因此,
eval
仅使用内置解释器计算表达式。这在汇编语言或编译语言中是不可能的。否,请参阅我的编辑。解释代码是。。。解释!字节码系统允许在计算机上节省时间