我的意思是:此版本(包括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