ネタ 2014-002

iPad mini RetinaをJailbreakして64bit ARM(AARCH64)のアセンブラを試してみた

去年(2013年)の秋に発売されたiPhone5sやiPad Air,iPad mini RetinaといったiOSマシンでは、A7という64bit ARM CPUを搭載しており、いち早く64bit ARM CPU用のソフトを自作して動かすことができる。

64bitのCPUでは、以前にも自分はAMD-64bit CPU用のアセンブラを試している。
今回はARMの64bit CPUで同じようにアセンブラを試してみたいと考えている。
手始めに、単純なHello worldのようなプログラムや、2つの数を加算するだけといったソフトを書いて動かしてみたい。

Appleの純正の開発環境でなく、Jailbreak(脱獄)iOSマシンの開発環境を使うとコマンドラインのソフトを開発して動かすことができる。
実際に、iPad mini Retina実機をJailbreakして試してみることにした。

ちなみに64bit ARMは、AARCH64というアーキテクチャの64bit CPUで、ARM v7やARM v7sの32bitのARMと比べると単純な拡張だけでなく割と別物なようだ。ARM v8と書くよりもARM64と書くみたいだ。


1. 使ったもの

・iPad mini Retina WiFi版(iOS7)
・MacBook Air (Mac OS X Mavericks)


2. 準備

(1)iPad mini RetinaをJailbreakする
 → iPad mini Retina(iOS7)をJailbreakしてみた
(2)MacBook(Mac OS X)にJailbreakマシンの開発環境Theosを入れる
 → iOSのJailbreak環境用の脱獄アプリ開発環境Theosをインストールしてみた


3. Hello worldを動かす手順

TheosをインストールしたMac上で下記のコマンドを入力する。

$THEOS/bin/nic.pl

次のように表示される。

NIC 1.0 - New Instance Creator
------------------------------
  [1.] iphone/application
  [2.] iphone/library
  [3.] iphone/preference_bundle
  [4.] iphone/tool
  [5.] iphone/tweak
Choose a Template (required):

ここで「iphone/tool」の

4

を入力し、次に

Project Name (required):

と聞かれるのでアプリ名として例えば

test64bit

と入力する。

次に、パッケージ名を聞かれるので、デフォルトのままにする。
次に、製作者名を聞かれるので、デフォルトのままにする。
あとは勝手にアプリのプロジェクト一式が自動生成される。(作業フォルダで実行すること)

作成された内容はこんな感じ。

 
 
cd test64bit
ls

 
Makefile control main.mm theos

作成されたフォルダ内に、Makefileとソースファイルmain.mmがあるので、まずmain.mmを次のように変更した。

 
 
 
 
 
 
 
 
 
int main(int argc, char **argv, char **evnp) {
#ifdef __LP64__
  printf("64bit\n");
#else
  printf("32bit\n");
#endif
  printf("Hello world.\n");
  return 0;
}

makeコマンドでビルドする。

 
make ARCHS=arm64

ソースファイルにエラーが無ければobjフォルダとその中にアプリが作られる。
作成されたバイナリが64bitになっているかどうかは、次のコマンドで確認ができる。

 
file obj/test64bit

とfileコマンドで確認できる。

 
obj/test64bit: Mach-O 64-bit executable

64bitのバイナリの実行ファイルは64bitのiOS機でしか実行することができない。
32bit機でも動かす場合にはFATバイナリという32bitと64bitと両方のコードを同梱すればよい。

 
make ARCHS='armv7 arm64'

とすればFATバイナリを生成することができる。

Makefileに

 
export ARCHS=armv7 arm64

というように追加するという方法もある。(普通はこっちの方法かも)

作成したtest64bitというファイルを実機に転送する。
実行すると、

 
 
64bit
Hello world.

と表示された。
ちゃんと64bit ARMのコードが動いているのが確認できた。



4. インラインアセンブラを使ってみる

参考文献として32bit ARM用の「ARMで学ぶアセンブリ言語入門」という本を参考にした。

プロジェクトの作成方法とかビルド方法は上記のHello worldと同様。
ソースコードmain.mmは次のように書いた。

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
long int addvalues(long int val1,long int val2)
{
  long int result;
  __asm__ (
    "ADD %[Rd],%[Rs1],%[Rs2]"
    : [Rd] "=r" (result)
    : [Rs1] "r" (val1), [Rs2] "r" (val2)
  );
  return result;
}
 
int main(int argc, char **argv, char **envp) {
 
  long int val=addvalues(1234567890123456789L,1L);
  printf("addvalues = %ld\n",val);
  return 0;
}

2つの数 1234567890123456789と1を加算するというコードである。
CPUのレジスタが64bitになったので、intの代わりにlong intを使う。
詳細は先ほどの参考書を参照のこと。

make ARCHS=arm64としてビルドし、iPad mini Retina実機で実行してみた。

結果、
addvalues = 1234567890123456790
と正しく加算結果が表示された。


インラインアセンブラで64bitの数値の加算のコードがうまく動いたのが確認できた。


5. 直接アセンブラを使ってみる (うまくいかなかった)

次に、インラインアセンブラでなく直接アセンブラのソースを記述するというのを試しているのだが、うまくいかない。
64bitのアセンブラが駄目なのかと、先ほどの参考書の32bit ARM用のアセンブラのサンプルコードをそのままというのも試したのだが、これもうまくいかなかった。アセンブリのソース ○○○.Sを記述したのをビルドして.oファイルは生成されているのだが、リンク時にその中にある関数が見つからないというエラーになってしまう。
(iOS用の開発環境でアセンブラを使う使い方について、もし情報があったらぜひ教えて下さい。)