Motorolaは、x86ベースのAndroid電話。ARM用に作成されたネイティブアプリ/ライブラリ(netflixなど)がこの電話でどのように動作するかについて少し混乱しています。
誰かが説明できるとありがたいです。
はい、ARMネイティブコードはHoudiniという名前のエミュレーション機能を使用してIntel x86で実行されます
このライブラリは、ARM命令をオンザフライで読み取り、それらを同等のx86命令に変換します。これが、多くのアプリが実際に同等のライブラリを構築しなくてもx86で動作する理由です。
実際には、異なるアーキテクチャの異なるネイティブコードを含めることができます。Netflixの実行方法はわかりませんが、apkを開くと/lib/armeabi-v7a/
ので、/lib/x86/
編集:armとx86のネイティブコードがあるAmazonショッピングアプリをチェックしました。多分それは、Netflixがそれを行う方法です。
Android Studio 3エミュレーターはバックエンドとしてQEMUを使用します
https://en.wikipedia.org/wiki/QEMU
QEMUは間違いなく主要なオープンソースクロスアーチエミュレーターです。これはGPLソフトウェアであり、x86およびARMに加えて、さらに多くのアーキテクチャをサポートしています。
その後、AndroidはQEMUにUIマジックを少し追加し、場合によってはいくつかのパッチを追加しますが、コアは間違いなくQEMUアップストリームにあります。
QEMUはバイナリ変換と呼ばれる手法を使用して、かなり高速なエミュレーションを実現します。 https://en.wikipedia.org/wiki/Binary_translation
バイナリ変換は、基本的にARM命令を同等のx86命令に変換します。
したがって、詳細を理解するための最良の方法は次のとおりです。
理論
したがって、十分なメモリがあれば、どのCPUも任意のCPUをエミュレートできることは明らかです。
難しい質問は、その方法fastです。
演習:QEMUユーザーモードシミュレーション
QEMUにはユーザーランドモードがあり、ゲストとホストが同じOSである限り、x86マシンでユーザーランドARMコードを簡単に操作して、何が起こっているかを確認できます。
このモードでは、バイナリ変換が基本的な指示を処理し、システムコールがホストシステムコールに転送されるだけです。
たとえば、Linux自立型(glibcなし)のHello Worldを使用したLinux on Linuxの場合:
main.S
.text
.global _start
_start:
asm_main_after_prologue:
/* write */
mov x0, 1
adr x1, msg
ldr x2, =len
mov x8, 64
svc 0
/* exit */
mov x0, 0
mov x8, 93
svc 0
msg:
.ascii "hello syscall v8\n"
len = . - msg
次に、次のようにアセンブルして実行します。
Sudo apt-get install qemu-user gcc-aarch64-linux-gnu
aarch64-linux-gnu-as -o main.o main.S
aarch64-linux-gnu-ld -o main.out main.o
qemu-aarch64 main.out
そして、期待される結果を出力します:
hello syscall v8
C標準ライブラリに対してコンパイルされたARMプログラムを実行して、プログラムをGDBステップデバッグすることもできます。この具体例を参照してください: シングルステップARM QEMU上のGDBでのアセンブリ?
バイナリ変換について説明しているため、ロギングを有効にして、QEMUが実行している正確な変換を確認することもできます。
qemu-aarch64 -d in_asm,out_asm main.out
ここに:
in_asm
はARMゲスト入力アセンブリを参照しますout_asm
は、実行されるX86ホスト生成アセンブリを指します出力には以下が含まれます。
----------------
IN:
0x0000000000400078: d2800020 mov x0, #0x1
0x000000000040007c: 100000e1 adr x1, #+0x1c (addr 0x400098)
0x0000000000400080: 58000182 ldr x2, pc+48 (addr 0x4000b0)
0x0000000000400084: d2800808 mov x8, #0x40
0x0000000000400088: d4000001 svc #0x0
OUT: [size=105]
0x5578d016b428: mov -0x8(%r14),%ebp
0x5578d016b42c: test %ebp,%ebp
0x5578d016b42e: jne 0x5578d016b482
0x5578d016b434: mov $0x1,%ebp
0x5578d016b439: mov %rbp,0x40(%r14)
0x5578d016b43d: mov $0x400098,%ebp
0x5578d016b442: mov %rbp,0x48(%r14)
0x5578d016b446: mov $0x4000b0,%ebp
0x5578d016b44b: mov 0x0(%rbp),%rbp
0x5578d016b44f: mov %rbp,0x50(%r14)
0x5578d016b453: mov $0x40,%ebp
0x5578d016b458: mov %rbp,0x80(%r14)
0x5578d016b45f: mov $0x40008c,%ebp
0x5578d016b464: mov %rbp,0x140(%r14)
0x5578d016b46b: mov %r14,%rdi
0x5578d016b46e: mov $0x2,%esi
0x5578d016b473: mov $0x56000000,%edx
0x5578d016b478: mov $0x1,%ecx
0x5578d016b47d: callq 0x5578cfdfe130
0x5578d016b482: mov $0x7f8af0565013,%rax
0x5578d016b48c: jmpq 0x5578d016b416
IN
セクションには、手書きのARMアセンブリコードが表示され、OUT
セクションには、生成されたx86アセンブリが表示されます。
Ubuntu 16.04 AMD64、QEMU 2.5.0、binutils 2.26.1でテスト済み。
QEMUフルシステムエミュレーション
ただし、QEMUでAndroidを起動すると、もちろんユーザーランドバイナリが実行されず、実際のLinuxカーネルとシミュレーション内のすべてのデバイスが実行される完全なシステムシミュレーションが実行されます。
完全なシステムシミュレーションはより正確ですが、少し遅くなり、QEMUにカーネルとディスクイメージを提供する必要があります。
それを試すには、次のセットアップを見てください。
[〜#〜] kvm [〜#〜]
QEMUでAndroid X86を実行すると、はるかに高速であることがわかります。
その理由は、QEMUが [〜#〜] kvm [〜#〜] を使用するためです。これは、ホスト上でゲスト命令を直接実行できるLinuxカーネル機能です。
強力なARMマシンを持っている場合(2019年の時点ではまだ珍しい)、ARMでARMを使用してKVMを実行することもできます。はるかに高速。
このため、X86ホストを使用している場合は、 Android AOSPカーネルをコンパイルし、Android Emulator? (低レベルのものに実際に触れる必要がない限り)。
Trend Micro Safe Mobile Workforce には、ARMアプリでのネイティブライブラリのランタイム(Intelのhoudiniではない)Android強力なx86サーバーでARM libのみでAPKを実行することをサポートできます。