首页 > 解决方案 > 是否有可能制作一个永远编写自己的汇编程序?

问题描述

基本上,您是否可以拥有在最后一行结束后不断编写新代码的汇编代码,以便尽管从有限数量的代码开始,它也可以永远保持直线运行?不允许循环。

标签: assemblycomputer-scienceinfinite

解决方案


它必须为某种具有无限磁带的机器(如图灵机)组装,否则你最终会到达地址空间的尽头。

除非您对指令指针有明确定义的非故障环绕语义。您需要一台在其可用地址空间中没有任何间隙的机器(所以不是 x86-64),而是具有 PC 相对寻址(所以不是 i386)。

可能是指令宽度与寄存器相同的 RISC,如 ARM。您将从几个指令开始,将 PC 相关存储的编码放入寄存器,然后运行它。

除了 ARM 没有一致的 I-cache 之外,大多数 RISC 也没有。也许是一个“简单”的 ARM,但实际的 Cortex-M0 不支持 4GiB 的 RAM。或者禁用 L1i/d-cache 的完整内核。

或者重复模式可以是 8 个字节,stp(存储对)/内存屏障。甚至stm(存储多个)允许使用单个指令存储多个单词,从而为包含多个刷新/屏障指令的模式腾出空间。

在重复模式和禁用中断之前需要多少个设置指令都没有关系。在第一次环绕之后,这些指令字节将被覆盖。

您需要禁用中断,因为您将覆盖内存的每个字节,包括中断向量表。除非您在具有虚拟内存的用户空间进程中执行此操作,例如 64 位内核下的 32 位进程,经过特殊修改以不保留任何用户空间页面。但是,在大多数 ISA 上,像中断表这样的内核/系统内容需要位于当前地址空间中,所以这可能不可行。页表使用物理地址,因此不必是当前虚拟地址空间的一部分。

虚拟内存可以让您将许多虚拟页面映射到同一个物理页面(因此您实际上会环绕同一个 4k 页面),因此您可以在 32 位机器上使用远低于 4G 的物理 RAM 来实现这一点,如果它有一个 MMU。(但就像我说的,你可能仍然需要禁用中断。)


当然,您可以想象一个简单的玩具 ISA 旨在使这成为可能,它不需要为任何东西保留地址空间的任何部分。


内存分段确实使这更容易:您可以在一个段内进行环绕,例如 16 位 x86 的 64kiB。但是,如果没有与 PC 相关的存储,您将无法轻松地创建一个实际存储在您正在执行的位置之前的 1 指令模式。

有趣的事实:8086 没有指令长度限制,实际上可以永远循环解码一个 64k 的充满前缀的代码段,没有操作码。( https://retrocomputing.stackexchange.com/questions/15050/what-s-the-last-x86-cpu-that-didn-t-place-a-limit-on-the-size-of-a-single -仪器

我不知道具有分段和 PC 相关商店的机器的具体示例。


推荐阅读