我的意思是:此版本(包括x86和ARM体系结构驱动程序)可以在x86计算机上运行,并且可以在其他ARM设备上运行。OS内核可以在x86和ARM上运行吗?
我知道现在没有这样的CPU支持两个指令集。但从理论上讲,它会成真吗?通电后,CPU可以检查程序所在的指令集是什么?
我的意思是:此版本(包括x86和ARM体系结构驱动程序)可以在x86计算机上运行,并且可以在其他ARM设备上运行。OS内核可以在x86和ARM上运行吗?
我知道现在没有这样的CPU支持两个指令集。但从理论上讲,它会成真吗?通电后,CPU可以检查程序所在的指令集是什么?
这主要是引导加载程序支持的问题,以及操作系统一旦加载的问题。这不仅是理论上的可能,对于版本的OSX的内核(/mach_kernel
)10.6.x的,10.7.x来作为通用的i386/x86_64的二进制代码:
$ file /Volumes/KernelDebugKit/mach_kernel
/Volumes/KernelDebugKit/mach_kernel: Mach-O universal binary with 2 architectures
/Volumes/KernelDebugKit/mach_kernel (for architecture x86_64): Mach-O 64-bit executable x86_64
/Volumes/KernelDebugKit/mach_kernel (for architecture i386): Mach-O executable i386
的10.5。X内核甚至专程为I386/PowerPC的通用二进制:
$file /Volumes/KernelDebugKit/mach_kernel
/Volumes/KernelDebugKit/mach_kernel: Mach-O universal binary with 2 architectures
/Volumes/KernelDebugKit/mach_kernel (for architecture i386): Mach-O executable i386
/Volumes/KernelDebugKit/mach_kernel (for architecture ppc): Mach-O executable ppc
引导程序(苹果公司的EFI固件实现(86)或的OpenFirmware(PPC)的OSX的情况下)需要支持“胖”的二进制格式并能够决定并运行正确的。当然,一旦加载内核,就需要操作系统其余部分的整个支持基础架构以兼容的格式提供,以便执行任何有用的操作。
请注意,早期版本的OSX甚至附带“Rosetta”,一个用于在x86/x86-64 CPU上运行PowerPC二进制文件的运行时二进制翻译系统。
要说清楚,内核的x86和ppc版本存储在同一个文件中是完全不相干的。
那么在我看来这不会成真。我的理由是: - 编译程序的两个版本比较容易,在安装期间可以决定它是在ARM还是x86平台上。
如果您正在查看32位命令。它们中的很多被使用,你需要加倍的指令集,这会降低你的CPU的效率。如果你不幸的话,32Bit指令集将满足你的需求,所以你将不得不改变到33Bit,这将是极其尴尬的。
真的,我不明白你为什么要这样做。它只是导致效率低下
我不这么认为,有两个指令集编写内核,并且具有执行不同的两种体系结构特殊启动代码,会调用相应的内核的可能性建筑。
这就是OS X的功能,内核包含所有支持的体系结构的代码,并且有一些特殊的引导代码可以为当前体系结构启动并运行所有代码。 – JustSid 2012-08-03 09:54:19
让我们假设它可以完成。需要做什么?
那么,你需要整个内核编译两次,一次使用x86,一次使用ARM操作码(汇编之后的汇编程序)。那么,我们所需要的只是一个小程序,它可以查询我们所在的CPU,然后分支到x86版本或ARM版本。
糟糕,有一个引导捆绑问题。你将使用哪两个操作码来确定要使用哪个版本? ARM或x86 - 记住它需要在两者上运行。
它可能是可能的。也许分支指令的编码是ARM上的一个nop或者某个东西。所以现在我可能能够有第一个指令是不同的x86和ARM - 其中之一分支一个短距离,我现在知道它是x86,并从那里跳到我的x86内核。而另一个不会采取分支,并会落入下面的代码,然后可以分支到ARM版本(反之亦然)。
这将是一个很棒的代码技巧。
但你为什么要这么做?你有一半的内核在内存中没有被使用(也许你可以把它换到磁盘上)。你也可以从一开始就为正确的目标进行编译。 (另外,我不确定是否有任何工具可以让你编译这两个内核并将它们放在一个图像中,但是如果你攻击了你自己的链接器,它可以完成)。
这是可能的。
除了戴夫和其他海报的答案,我写了一个python脚本,将产生代码欺骗,将在x86和ARM上运行,这将取决于引导的路径采取不同的路径。
我不熟悉x86,所以请原谅我,如果这不起作用。
import sys
import struct
import math
armClobberReg = 0
armShift = 31
if (armClobberReg>15):
sys.stderr.write("Error! ARM clobber register is invalid\n")
sys.exit(-1)
if (armClobberReg == 15):
sys.stderr.write("Warning: r15 will be clobbered on ARM\n")
if (armShift & 1 != 1 or armShift > 31):
sys.stderr.write("Warning! ARM shift is invalid. Using 31 instead\n")
armShift = 31
jmpOffset = (armClobberReg<<4)|(armShift>>1)
jmpAndEqNopInstruction = struct.pack("<BBBBI",0xE9, jmpOffset,0,0,0xE1A00000)
armNoOp = struct.pack("<I",0xE1A00000)
x86NoOp = struct.pack("c","\x90")
asmOut = jmpAndEqNopInstruction
asmArmTxtOut = "{0:08x}: andeq r{1}, r0, r9, ror #{2}\n".format(0, armClobberReg, armShift)
asmArmTxtOut+= "{0:08x}: nop\n".format(4)
asmx86TxtOut = "{0:08x}: jmp {1:x}\n".format(0, jmpOffset)
asmx86TxtOut+= " ... (ARM instructions)\n"
i = math.floor((jmpOffset + 5)/4) - 2
armPc = 8
while i>0:
asmOut += armNoOp
asmArmTxtOut+= "{0:08x}: nop <replace with your arm instructions>\n".format(armPc)
armPc+=4
i-=1
asmOut = asmOut.ljust(jmpOffset + 5, chr(0xff))
asmOut += x86NoOp
asmx86TxtOut += "{0:08x}: nop <replace with your x86 instructions>\n".format(jmpOffset + 5)
asmArmTxtOut += " ... (x86 instructions)\n"
sys.stderr.write("x86 disassembly: \n"+asmx86TxtOut+"\n")
sys.stderr.write("ARM disassembly: \n"+asmArmTxtOut+"\n")
sys.stderr.write("ARM code length limited to {0} instructions\n".format(int(math.floor((jmpOffset + 5)/4) - 2)))
sys.stdout.write(asmOut)
sys.stderr.write("Wrote opcodes to stdout\n\n")
在ARM,同时在x86,它被解释为jmp
指令所述第一和第二指令被解释为andeq
和nop
指令。
ARM拆解:
86拆卸:
您可以将自己的操作码在里面,将跳转到相应的内核。
你的问题令人困惑/困惑。你的第一段会问:“我们可以建立一个运行在x86和ARM上的内核吗?”。你的第二段提出了一个完全不同的问题:“*我们可以建立一个CPU来计算程序使用的ISA,并相应地改变它的行为吗?*”。 – ArjunShankar 2012-08-03 14:18:49
谢谢。在第二段中,我提出了一种可以实现内核在两种架构上运行的方法。 – 2012-08-07 06:53:27