assembly - QEMU 是否使用与 x86 到 x86 仿真的 guest 寄存器相同的主机寄存器?

标签 assembly x86 emulation qemu

我正在研究像 Bochs 和 QEMU 这样的模拟器是如何工作的,并且有一个问题 - 如果我在 x86 主机上模拟 x86 客户机操作系统并且客户机执行一些分配寄存器的指令(例如,mov eax 3) ,是否保证或者甚至可能在模拟器运行的代码中将值实际分配给实际硬件上的 eax 寄存器?

我认为没有理由不这样做,因为 QEMU 进程是它自己的独立进程(因此它不必与任何其他进程共享通用寄存器)并且因为主机和 guest 都架构相同,因此具有相同的通用寄存器。

另外,如果我要在 QEMU 中执行一个包含两条指令的程序:

mov eax 3
add eax 2

如果它可以确定这样做不会改变程序的执行,它是否会将两者组合成单个 mov eax, 5 指令,因为它通过执行指令 block 而不是每个指令 block 来执行程序单独指导?

请注意,在这种情况下,我指的是纯仿真(Bochs 或非 KVM QEMU),而不是硬件虚拟化。

最佳答案

不,QEMU 不能那样工作。 x86-to-x86 不是特殊情况,其处理方式与仿真中的任何其他 guest /主机组合一样。所有 guest 代码首先被翻译成中间表示。然后运行一个简单的优化过程(这是我们发现“加载 2;添加 3”简化为“加载 5”的地方)。最后,我们进行寄存器分配并从 IR 生成 native 主机代码。

在 IR guest 寄存器中,用“TCG 值”表示,这有点像高级语言中的变量。 guest 寄存器被定义为存在于主机内存中的 CPU 状态结构中的值,但 TCG 足够聪明,不会在实际需要之前将它们写回内存,因此 guest 寄存器的“实时”副本通常会在主机寄存器中。但是因为寄存器分配是一段完全独立的代码,分配器不太可能碰巧选择客户代码最初使用的同一个 x86 寄存器。

使用像这样的 IR 是编译器或 JIT 的一种非常常见的设计模式(TCG QEMU 是一种 JIT)。优点是很容易支持多个前端和后端,而您需要考虑的不同组合的数量不会激增; QEMU 目前支持 18 个前端和 9 个后端。这也意味着常见的优化(比如移除单独的 add 指令的常量折叠)只需要实现一次,完全在 IR 上工作。

TCG IR 在此处记录:http://wiki.qemu.org/Documentation/TCG

关于assembly - QEMU 是否使用与 x86 到 x86 仿真的 guest 寄存器相同的主机寄存器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41028273/

相关文章:

javascript - 模拟移动连接

c++ - 查询关于 pe_coff 规范的 mark peter 文章

linux - 为什么 Linux 程序的 .text 部分从 0x0804800 开始,堆栈顶部从 0xbffffff 开始?

assembly - 为什么在xv6中gdtdesc中有sizeof(gdt)-1

c++ - _asm 交换和编译器添加

operating-system - 推荐一个简单的 x86 模拟器和操作系统

android - GCM - Android 模拟器上的 PHONE_REGISTRATION_ERROR

assembly - "self-modified link"在 Pegasus 编程中如何工作?

c++ - C++ 的汇编程序输出中的重复析构函数

assembly - 为什么 Bochs 上的分页不起作用并且获取物理地址不可用错误