つまり、このビルド(x86とARMアーキテクチャドライバーの両方を含む)はx86コンピューターで実行でき、他のARMデバイスでも実行できます。
現在、両方の命令セットをサポートするCPUはありません。しかし、理論的には、それは実現するのでしょうか?電源を入れると、CPUはプログラムがどの命令セットにあるかを確認できますか?
つまり、このビルド(x86とARMアーキテクチャドライバーの両方を含む)はx86コンピューターで実行でき、他のARMデバイスでも実行できます。
現在、両方の命令セットをサポートするCPUはありません。しかし、理論的には、それは実現するのでしょうか?電源を入れると、CPUはプログラムがどの命令セットにあるかを確認できますか?
可能です。
デイブと他のポスターの回答に加えて、x86 と ARM の両方で実行されるコードのトリックを生成する Python スクリプトを作成しました。
私は 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 では、1 番目と 2 番目の命令はandeq
andnop
命令として解釈されますが、x86 では命令として解釈されjmp
ます。
アームの分解:
x86 分解:
適切なカーネルに分岐する独自のオペコードを追加できます。
それができると仮定しましょう。何をする必要がありますか?
1 回は x86 を使用し、もう 1 回は ARM オペコード (アセンブル後のアセンブラー) を使用して、カーネル全体を 2 回コンパイルする必要があります。では、必要なのは、使用している CPU を照会し、x86 バージョンまたは ARM バージョンのいずれかに分岐する小さなプログラムだけです。
おっと、ブート ストラップの問題があります。どのバージョンを使用するかを判断するために、2 つのオペコードのどちらを使用しますか? ARM または x86 - 両方で実行する必要があることに注意してください。
それは可能かもしれません。おそらく、分岐命令のエンコーディングは、ARM の nop か何かです。したがって、x86 と ARM の両方で最初の命令を異なるものにすることができるかもしれません。そのうちの 1 つは短い距離で分岐し、それが x86 であることがわかり、そこから x86 カーネルにジャンプします。そして、もう一方は分岐を取らず、下のコードにフォールスルーし、ARM バージョンに分岐する可能性があります (またはその逆)。
それは素晴らしいコード トリックです。
しかし、なぜそれをしたいのですか?メモリ内のカーネルの半分が使用されていない可能性があります (おそらくディスクにスワップアウトできます)。また、最初から適切なターゲット用にコンパイルすることもできます。(また、2 つのカーネルをコンパイルして 1 つのイメージに配置できるツールについてはわかりませんが、独自のリンカーをハッキングすれば実行できます)。
これは主に、ブートローダーでのサポートの問題と、ロードされた OS の動作の問題です。/mach_kernel
理論的に可能であるだけでなく、バージョン 10.6.x ~ 10.7.x のOSX カーネル ( ) はユニバーサル 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
ブートローダー (OSX の場合は Apple の EFI ファームウェア実装 (x86) または OpenFirmware (ppc)) は、「ファット」バイナリ形式をサポートし、正しいものを決定して実行できる必要があります。もちろん、カーネルがロードされたら、有用なことを行うために、残りのオペレーティング システムのサポート インフラストラクチャ全体を互換性のある形式で利用できるようにする必要があります。
OSX の古いバージョンには、x86/x86-64 CPU で PowerPC バイナリを実行するためのランタイム バイナリ変換システムである「Rosetta」が同梱されていたことに注意してください。
明確にするために、カーネルの x86 バージョンと ppc バージョンが同じファイルに格納されていることはまったく関係ありません。
私の意見では、これは実現しません。私の理由は次のとおりです。 - プログラムの 2 つのバージョンをコンパイルする方が簡単で、インストール中に ARM または x86 プラットフォーム上にあるかどうかを判断できます。
32 ビット コマンドを見ている場合。それらの多くが使用され、CPU の効率を低下させる命令セットを 2 倍にする必要があります。運が悪ければ、32 ビットの命令セットでニーズが満たされないため、33 ビットに変更する必要があり、これは非常に厄介です。
なぜあなたがこれをしたいのか本当にわかりません。非効率になるだけ