我一直在学习汇编,并且我读到四个主要的 x86 通用寄存器(eax、ebx、ecx 和 edx)每个都有一个预期或建议的用途。例如,eax 是累加器寄存器,ecx 用作循环的计数器,等等。大多数编译器是否尝试将寄存器用于建议的目的,或者他们是否忽略了寄存器“应该”的用途而只是将值分配给下一个可用的寄存器?
此外,在查看 x64 寄存器时,我注意到添加了额外的 8 个通用寄存器,如果忽略 rbp、rsp、rsi 和 rdi(因为它们具有非通用用途),gp 寄存器的总数将达到 12 ),如果包括它们,则为十六个。在普通用户程序(即浏览器、文字处理器等,而不是需要大量寄存器的密码程序)中,在任何给定时间通常使用多少这些寄存器?像 Firefox 这样的程序一次使用所有 12/16 个普通寄存器是常见的,还是因为它们没有足够的变量来填充它们而只使用一个子集?我将通过反汇编二进制文件来自己研究这个问题,看看一般情况是什么,但我希望能得到比我更有见识的人的回答。
此外,如果当前未用于非通用应用程序,编译器是否通常将 semi-gp 寄存器(rsi、rdi、rsp 和 rbp)用于通用用途?我很好奇,因为我看到这些寄存器被列为“通用”,但即使我能想到这些寄存器不能用于通用存储的实例(例如,你不想存储rbp 和 rsp 变量,然后将值推入堆栈!)。那么编译器会尽量使用这些寄存器吗?x86 和 x64 编译之间是否有区别,因为 x64 处理器有更多可用寄存器,因此没有必要将变量填充到任何可用寄存器中?
我正在研究像Bochs和QEMU这样的模拟器是如何工作的并且有一个问题 - 如果我在x86主机上模拟x86客户操作系统并且guest执行一些指令来分配寄存器(例如,mov eax 3),是吗保证甚至可能将该值实际分配给仿真器运行的代码中的实际硬件上的eax寄存器?
我假设没有理由不这样做,因为QEMU进程是它自己的独立进程(所以它不必与任何其他进程共享通用寄存器),因为主机和客户机架构都是相同,因此具有相同的通用寄存器.
另外,如果我要在QEMU中执行一个有两条指令的程序:
mov eax 3
add eax 2
Run Code Online (Sandbox Code Playgroud)
mov eax, 5如果可以确定这样做不会改变程序的执行,它会将两者合并为一条指令,因为它通过执行指令块而不是单独执行每条指令来执行程序吗?
请注意,在这种情况下,我指的是纯仿真(Bochs或非KVM QEMU),而不是硬件虚拟化.