Asm:将汇编指令移动到特定地址

Asm: Moving assembly instructions to specific address

好吧,我正在尝试找到一条汇编指令,将整个指令移动到特定地址(与指令的大小无关)。如果没有这样的说明,谁能给我一些关于如何在没有系统调用或其他软件的情况下实现多线程的想法?换句话说,假设我正在制作自己的操作系统,如何在汇编中使用高效代码启用多线程?

关于如何在原始汇编中实现多线程的问题:现代 32 位 x86 处理器具有对任务切换的硬件支持。您可以使用它来实现多任务处理(具有不同地址的多个进程 spaces)and/or 多线程(单个进程中的多个执行线程)。

此功能记录在 Intel 64 and IA-32 Architectures Software Developer's Manual,第 3 卷,第 7 章,任务管理中。 注意:阅读和理解这份 4700 页的文档可能需要 12 年的时间。

使用此硬件支持是获得某些东西的最直接方式 运行 但可能不是最有效的方式。基于 x86 的操作系统很早就从这种方式转移到手动任务切换。这允许系统实现 CPU 未提供的切换功能,并且还可以在完全切换过度时执行优化切换。这种方法变得如此普遍,以至于 x86 处理器的 64 位长模式放弃了硬件任务管理支持。现代操作系统使用手动任务切换。


关于将移动指令作为实现多线程的一种方式的想法,我认为您的概念是在需要切换到新代码时围绕地址 space 移动代码。有 2 种替代技术可以消除执行此操作的需要。

首先,您可以跳转到其他位置的代码,而不是移动代码。早期的多任务操作系统,例如 PDP-11 上的 Unix,就使用了这种技术。您可以将所有活动程序加载到不同位置的内存中,设置一个周期性中断以经常将控制权交给您的系统软件,并在每次中断时选择下一个要跳转到的程序。系统应跟踪每个程序停止的位置,以便它可以在同一位置继续。

第二种方法依赖于虚拟内存。还有一个物理内存space。最重要的是,定义了多个 "virtual" 内存 space。在任何给定时间,只有 1 个虚拟内存 space 处于活动状态。每当访问内存时,系统都会将虚拟地址转换为某个物理地址。访问内存的程序只能看到自己的虚拟地址space.

每个任务都有自己的地址space。切换到新任务时,系统会激活其私有地址 space,然后在上次暂停在私有地址 space 的位置恢复执行。不是在单个共享地址 space 周围移动东西,甚至不是在共享地址 space 中从一个地方跳到另一个地方,而是实际上定义了一整套单独的地址 space。您根据需要转移到新的 spaces。

现代多线程在很大程度上依赖于这种方法。每个进程都会有一个私有地址space;系统会根据需要在它们之间切换。一个进程将有 1+ 个线程。进程中的每个线程共享相同的地址 space。然后,每个线程存储的所有内容都是上次暂停执行的位置。切换到同一进程中的新线程会保留当前地址 space 并在其中跳转到新线程上次暂停的位置。


关于如何移动指令的问题,汇编语言不提供这种能力。这不是一件常见的事情。如果你想在内存中操作机器代码,你可能想使用像 Intel X86 Encoder Decoder library 这样的库。像这样的库了解存在的指令和机器代码的字节格式。这使它能够将字节序列解释为一条指令。

一旦您知道以下指令有多大,在汇编中移动该字节数就很容易了。在 x86 中,您将使用 mov 指令。