プログラムはNativeで実行

さて、気を取り直して先ほどのList1のLチカを実行。Pin 13とGNDの間にLEDを繋いで動作させてみた。Sketch Sizeは49,046 Bytesで全体の18%(最大262,144Bytes)となる。内部はスクリプトが色々動いているようで、Arduino IDEのステータス欄に色々動作状態が出てくる(Photo18)。

Photo18: これは冒頭の方。実際はこの後延々と転送メッセージが流れてくる。

で、肝心の動作は? というと、最初ACを繋いだ状態だとLEDが微妙に点灯しているだけ(Photo19)だが、Sketchをロードするとちゃんと1秒間隔で点滅を繰り返す(Photo20)。で、USBケーブルを抜いても問題なく動作は継続する(Photo21)。問題はここで一度ACアダプタを抜いて、再度ACアダプタを接続した場合。Arduinoの場合だと、SketchはFlash Memoryに格納されるから、電源を入れればPower on bootでFlashからSketchが読み出され、再び勝手に実行を始める。ところがGalileoの場合はPhoto19の状態に戻ってしまうのだ。つまりGalileoのArduino互換モードでは、SketchはFlash MemoryではなくSRAMに格納されるようだ。先にSketchの最大サイズが256KBと書いたが、おそらくSRAMの半分をSystemで、残りをSketchで利用しているのだろう。

Photo19: この状態だとI2C経由のGPIOがまだ初期化がなされておらず、Hi-Z状態になっているのではないかと思われる。この状態における明るさ(≒Hi-Zにおいて流れる電圧)はArduinoよりも間違いなく高いようだ。

Photo20: 輝度はこんなもんだろう。

Photo21: ケーブルが抜けてもちゃんと点灯しているのが判る。

このあたりでArduino互換とは言え、使い方にちょっと制約が出てくる気がするが、それはさておきファイルサイズの話。同じSketchをArduino UNO用にビルドすると1,076Bytesである。アーキテクチャが違うとはいえ、何でここまでファイルサイズが違うのか? ということで、ちょっとバイナリを確認してみることにした。

Galileo向けのArduino IDEでは最終的にELFフォーマットでバイナリを生成するようだ。先のPhoto18にもちょっと出てくるが、Galileo用Arduino IDEは自動でユーザーディレクトリの下の方(詳しくはPhoto18を参照)にディレクトリを作り、その中にファイルを生成する(Photo22)。で、この中にある.elfファイルがGalileoにダウンロードされるものの様だ。そこでobjdumpを使って中身をちょっと確認してみた。まずobjdump -xでヘッダ情報を出したのがList 2である。ファイルフォーマットはelf32-i386なので、つまりこのSketchはGalileoでNativeで実行できるようになっていると考えられる。

Photo22: ディレクトリのbuildXXXXXXはビルドを行うたびに自動生成となる模様。

■ List 2

objdump -x C:\Users\kuma\Desktop\Galileo_001.cpp.elf

C:\Users\kuma\Desktop\Galileo_001.cpp.elf:     file format elf32-i386
C:\Users\kuma\Desktop\Galileo_001.cpp.elf
architecture: i386, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x08048e64

Program Header:
    PHDR off    0x00000034 vaddr 0x08048034 paddr 0x08048034 align 2**2
         filesz 0x00000100 memsz 0x00000100 flags r-x
  INTERP off    0x00000134 vaddr 0x08048134 paddr 0x08048134 align 2**0
         filesz 0x00000014 memsz 0x00000014 flags r--
    LOAD off    0x00000000 vaddr 0x08048000 paddr 0x08048000 align 2**12
         filesz 0x00004e28 memsz 0x00004e28 flags r-x
    LOAD off    0x00005000 vaddr 0x0804d000 paddr 0x0804d000 align 2**12
         filesz 0x00006b20 memsz 0x0000729c flags rw-
 DYNAMIC off    0x00005018 vaddr 0x0804d018 paddr 0x0804d018 align 2**2
         filesz 0x000000e8 memsz 0x000000e8 flags rw-
    NOTE off    0x00000148 vaddr 0x08048148 paddr 0x08048148 align 2**2
         filesz 0x00000024 memsz 0x00000024 flags r--
EH_FRAME off    0x00004448 vaddr 0x0804c448 paddr 0x0804c448 align 2**2
         filesz 0x000001a4 memsz 0x000001a4 flags r--
   STACK off    0x00000000 vaddr 0x00000000 paddr 0x00000000 align 2**2
         filesz 0x00000000 memsz 0x00000000 flags rw-

Dynamic Section:
  NEEDED               libpthread.so.0
  NEEDED               libstdc++.so.6
  NEEDED               libm.so.0
  NEEDED               libgcc_s.so.1
  NEEDED               libc.so.0
  INIT                 0x080489e0
  FINI                 0x0804b32c
  GNU_HASH             0x0804816c
  STRTAB               0x08048510
  SYMTAB               0x080481b0
  STRSZ                0x000002aa
  SYMENT               0x00000010
  DEBUG                0x00000000
  PLTGOT               0x0804d100
  PLTRELSZ             0x00000148
  PLTREL               0x00000011
  JMPREL               0x08048898
  REL                  0x08048878
  RELSZ                0x00000020
  RELENT               0x00000008
  VERNEED              0x08048828
  VERNEEDNUM           0x00000002
  VERSYM               0x080487ba

Version References:
  required from libstdc++.so.6:
    0x056bafd3 0x00 04 CXXABI_1.3
    0x08922974 0x00 03 GLIBCXX_3.4
  required from libgcc_s.so.1:
    0x0d696910 0x00 02 GLIBC_2.0

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .interp       00000014  08048134  08048134  00000134  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  1 .note.gnu.build-id 00000024  08048148  08048148  00000148  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .gnu.hash     00000044  0804816c  0804816c  0000016c  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  3 .dynsym       00000360  080481b0  080481b0  000001b0  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .dynstr       000002aa  08048510  08048510  00000510  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  5 .gnu.version  0000006c  080487ba  080487ba  000007ba  2**1
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  6 .gnu.version_r 00000050  08048828  08048828  00000828  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  7 .rel.dyn      00000020  08048878  08048878  00000878  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  8 .rel.plt      00000148  08048898  08048898  00000898  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  9 .init         0000001c  080489e0  080489e0  000009e0  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 10 .plt          000002a0  08048a00  08048a00  00000a00  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 11 .text         0000268c  08048ca0  08048ca0  00000ca0  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 12 .fini         00000017  0804b32c  0804b32c  0000332c  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 13 .rodata       00001100  0804b348  0804b348  00003348  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 14 .eh_frame_hdr 000001a4  0804c448  0804c448  00004448  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 15 .eh_frame     0000083c  0804c5ec  0804c5ec  000045ec  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 16 .ctors        0000000c  0804d000  0804d000  00005000  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 17 .dtors        00000008  0804d00c  0804d00c  0000500c  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 18 .jcr          00000004  0804d014  0804d014  00005014  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 19 .dynamic      000000e8  0804d018  0804d018  00005018  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 20 .got.plt      000000b0  0804d100  0804d100  00005100  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 21 .data         00006970  0804d1b0  0804d1b0  000051b0  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 22 .bss          0000077c  08053b20  08053b20  0000bb20  2**5
                  ALLOC
 23 .comment      00000011  00000000  00000000  0000bb20  2**0
                  CONTENTS, READONLY
SYMBOL TABLE:
no symbols

んではobjdump -dでディスアセンブルするとどうなるか、をリスト全部掲載すると長すぎるので抜粋をList 3に。.initはもうファームウェアの初期化ルーチンを呼んでるだけだし、.pltは処理テーブルがひたすら並んでいるだけである。で、こまごましたものは.textに全部突っ込んであるが、明らかに今回の処理と無関係な関数のディスパッチルーチンまで含まれており、このあたりが無駄に突っ込まれている結果としてファイルサイズはかなり大きくなっていると考えられる(ちなみにobjdumpで -Sオプションをつけてもソースは表示されなかったので、g++でデバッグオプションは付加されていない模様)。

■ List 3

objdump -d C:\Users\kuma\Desktop\Galileo_001.cpp.elf

C:\Users\kuma\Desktop\Galileo_001.cpp.elf:     file format elf32-i386


Disassembly of section .init:

080489e0 <_init>:
 80489e0:   55                      push   %ebp
 80489e1:   89 e5                   mov    %esp,%ebp
 80489e3:   53                      push   %ebx
 80489e4:   e8 9d 04 00 00          call   8048e86 <strcpy@plt+0x1f6>
 80489e9:   81 c3 17 47 00 00       add    $0x4717,%ebx
 80489ef:   e8 56 05 00 00          call   8048f4a <strcpy@plt+0x2ba>
 80489f4:   e8 17 29 00 00          call   804b310 <strcpy@plt+0x2680>
 80489f9:   5b                      pop    %ebx
 80489fa:   5d                      pop    %ebp
 80489fb:   c3                      ret    

Disassembly of section .plt:

08048a00 <__deregister_frame_info@plt-0x10>:
 8048a00:   ff 35 04 d1 04 08       pushl  0x804d104
 8048a06:   ff 25 08 d1 04 08       jmp    *0x804d108
 8048a0c:   00 00                   add    %al,(%eax)
    ...

08048a10 <__deregister_frame_info@plt>:
 8048a10:   ff 25 0c d1 04 08       jmp    *0x804d10c
 8048a16:   68 00 00 00 00          push   $0x0
 8048a1b:   e9 e0 ff ff ff          jmp    8048a00 <_init+0x20>

08048a20 <rewind@plt>:
 8048a20:   ff 25 10 d1 04 08       jmp    *0x804d110
 8048a26:   68 08 00 00 00          push   $0x8
 8048a2b:   e9 d0 ff ff ff          jmp    8048a00 <_init+0x20>

08048a30 <__errno_location@plt>:
 8048a30:   ff 25 14 d1 04 08       jmp    *0x804d114
 8048a36:   68 10 00 00 00          push   $0x10
 8048a3b:   e9 c0 ff ff ff          jmp    8048a00 <_init+0x20>

08048a40 <open@plt>:
 8048a40:   ff 25 18 d1 04 08       jmp    *0x804d118
 8048a46:   68 18 00 00 00          push   $0x18
 8048a4b:   e9 b0 ff ff ff          jmp    8048a00 <_init+0x20>

08048a50 <fwrite@plt>:
 8048a50:   ff 25 1c d1 04 08       jmp    *0x804d11c
 8048a56:   68 20 00 00 00          push   $0x20
 8048a5b:   e9 a0 ff ff ff          jmp    8048a00 <_init+0x20>

08048a60 <usleep@plt>:
 8048a60:   ff 25 20 d1 04 08       jmp    *0x804d120
 8048a66:   68 28 00 00 00          push   $0x28
 8048a6b:   e9 90 ff ff ff          jmp    8048a00 <_init+0x20>

(中略)

08048c60 <printf@plt>:
 8048c60:   ff 25 a0 d1 04 08       jmp    *0x804d1a0
 8048c66:   68 28 01 00 00          push   $0x128
 8048c6b:   e9 90 fd ff ff          jmp    8048a00 <_init+0x20>

08048c70 <puts@plt>:
 8048c70:   ff 25 a4 d1 04 08       jmp    *0x804d1a4
 8048c76:   68 30 01 00 00          push   $0x130
 8048c7b:   e9 80 fd ff ff          jmp    8048a00 <_init+0x20>

08048c80 <pipe2@plt>:
 8048c80:   ff 25 a8 d1 04 08       jmp    *0x804d1a8
 8048c86:   68 38 01 00 00          push   $0x138
 8048c8b:   e9 70 fd ff ff          jmp    8048a00 <_init+0x20>

08048c90 <strcpy@plt>:
 8048c90:   ff 25 ac d1 04 08       jmp    *0x804d1ac
 8048c96:   68 40 01 00 00          push   $0x140
 8048c9b:   e9 60 fd ff ff          jmp    8048a00 <_init+0x20>

Disassembly of section .text:

08048ca0 <.text>:
 8048ca0:   8d 4c 24 04             lea    0x4(%esp),%ecx
 8048ca4:   83 e4 f0                and    $0xfffffff0,%esp
 8048ca7:   ff 71 fc                pushl  -0x4(%ecx)
 8048caa:   55                      push   %ebp
 8048cab:   89 e5                   mov    %esp,%ebp
 8048cad:   56                      push   %esi
 8048cae:   53                      push   %ebx
 8048caf:   51                      push   %ecx
 8048cb0:   83 ec 10                sub    $0x10,%esp
 8048cb3:   8b 31                   mov    (%ecx),%esi
 8048cb5:   8b 59 04                mov    0x4(%ecx),%ebx
 8048cb8:   ff 35 20 3b 05 08       pushl  0x8053b20
 8048cbe:   68 c6 c2 04 08          push   $0x804c2c6
 8048cc3:   68 0c b6 04 08          push   $0x804b60c
 8048cc8:   e8 83 fe ff ff          call   8048b50 <freopen@plt>
 8048ccd:   83 c4 10                add    $0x10,%esp
 8048cd0:   a3 20 3b 05 08          mov    %eax,0x8053b20
 8048cd5:   85 c0                   test   %eax,%eax
 8048cd7:   75 14                   jne    8048ced <strcpy@plt+0x5d>
 8048cd9:   51                      push   %ecx
 8048cda:   51                      push   %ecx
 8048cdb:   ff 35 6c 3b 05 08       pushl  0x8053b6c
 8048ce1:   68 19 b6 04 08          push   $0x804b619
 8048ce6:   e8 f5 fe ff ff          call   8048be0 <fputs@plt>
 8048ceb:   eb 3a                   jmp    8048d27 <strcpy@plt+0x97>
 8048ced:   83 ec 0c                sub    $0xc,%esp
 8048cf0:   50                      push   %eax
 8048cf1:   e8 fa fe ff ff          call   8048bf0 <fflush@plt>
 8048cf6:   83 c4 0c                add    $0xc,%esp
 8048cf9:   ff 35 6c 3b 05 08       pushl  0x8053b6c
 8048cff:   68 c6 c2 04 08          push   $0x804c2c6
 8048d04:   68 33 b6 04 08          push   $0x804b633
 8048d09:   e8 42 fe ff ff          call   8048b50 <freopen@plt>
 8048d0e:   83 c4 10                add    $0x10,%esp
 8048d11:   a3 6c 3b 05 08          mov    %eax,0x8053b6c
 8048d16:   85 c0                   test   %eax,%eax
 8048d18:   75 19                   jne    8048d33 <strcpy@plt+0xa3>
 8048d1a:   83 ec 0c                sub    $0xc,%esp
 8048d1d:   68 43 b6 04 08          push   $0x804b643
 8048d22:   e8 49 ff ff ff          call   8048c70 <puts@plt>
 8048d27:   c7 04 24 ff ff ff ff    movl   $0xffffffff,(%esp)
 8048d2e:   e8 0d ff ff ff          call   8048c40 <exit@plt>
 8048d33:   83 ec 0c                sub    $0xc,%esp
 8048d36:   50                      push   %eax
 8048d37:   e8 b4 fe ff ff          call   8048bf0 <fflush@plt>
 8048d3c:   83 c4 10                add    $0x10,%esp
 8048d3f:   83 fe 02                cmp    $0x2,%esi
 8048d42:   7e 52                   jle    8048d96 <strcpy@plt+0x106>
 8048d44:   ff 73 08                pushl  0x8(%ebx)
 8048d47:   ff 73 04                pushl  0x4(%ebx)
 8048d4a:   ff 33                   pushl  (%ebx)
 8048d4c:   68 70 b6 04 08          push   $0x804b670
 8048d51:   e8 0a ff ff ff          call   8048c60 <printf@plt>
 8048d56:   5a                      pop    %edx
 8048d57:   ff 35 20 3b 05 08       pushl  0x8053b20
 8048d5d:   e8 8e fe ff ff          call   8048bf0 <fflush@plt>
 8048d62:   59                      pop    %ecx
 8048d63:   58                      pop    %eax
 8048d64:   6a 00                   push   $0x0
 8048d66:   6a 01                   push   $0x1
 8048d68:   e8 22 20 00 00          call   804ad8f <strcpy@plt+0x20ff>
 8048d6d:   c7 04 24 01 00 00 00    movl   $0x1,(%esp)
 8048d74:   e8 f5 20 00 00          call   804ae6e <strcpy@plt+0x21de>
 8048d79:   e8 db 12 00 00          call   804a059 <strcpy@plt+0x13c9>
 8048d7e:   58                      pop    %eax
 8048d7f:   5a                      pop    %edx
 8048d80:   53                      push   %ebx
 8048d81:   56                      push   %esi
 8048d82:   e8 b3 0c 00 00          call   8049a3a <strcpy@plt+0xdaa>
 8048d87:   e8 06 02 00 00          call   8048f92 <strcpy@plt+0x302>
 8048d8c:   83 c4 10                add    $0x10,%esp
 8048d8f:   e8 12 02 00 00          call   8048fa6 <strcpy@plt+0x316>
 8048d94:   eb f9                   jmp    8048d8f <strcpy@plt+0xff>
 8048d96:   50                      push   %eax
 8048d97:   50                      push   %eax
 8048d98:   ff 35 6c 3b 05 08       pushl  0x8053b6c
 8048d9e:   68 5c b6 04 08          push   $0x804b65c
 8048da3:   e8 38 fe ff ff          call   8048be0 <fputs@plt>
 8048da8:   8d 65 f4                lea    -0xc(%ebp),%esp
 8048dab:   83 c8 ff                or     $0xffffffff,%eax
 8048dae:   59                      pop    %ecx
 8048daf:   5b                      pop    %ebx
 8048db0:   5e                      pop    %esi
 8048db1:   5d                      pop    %ebp
 8048db2:   8d 61 fc                lea    -0x4(%ecx),%esp
 8048db5:   c3                      ret    

(中略)

 804b2d2:   55                      push   %ebp
 804b2d3:   89 e5                   mov    %esp,%ebp
 804b2d5:   57                      push   %edi
 804b2d6:   56                      push   %esi
 804b2d7:   53                      push   %ebx
 804b2d8:   83 ec 1c                sub    $0x1c,%esp
 804b2db:   31 f6                   xor    %esi,%esi
 804b2dd:   8b 5d 0c                mov    0xc(%ebp),%ebx
 804b2e0:   8b 45 10                mov    0x10(%ebp),%eax
 804b2e3:   01 d8                   add    %ebx,%eax
 804b2e5:   8b 7d 08                mov    0x8(%ebp),%edi
 804b2e8:   89 45 e4                mov    %eax,-0x1c(%ebp)
 804b2eb:   eb 11                   jmp    804b2fe <strcpy@plt+0x266e>
 804b2ed:   0f b6 0b                movzbl (%ebx),%ecx
 804b2f0:   50                      push   %eax
 804b2f1:   50                      push   %eax
 804b2f2:   8b 07                   mov    (%edi),%eax
 804b2f4:   51                      push   %ecx
 804b2f5:   57                      push   %edi
 804b2f6:   43                      inc    %ebx
 804b2f7:   ff 10                   call   *(%eax)
 804b2f9:   83 c4 10                add    $0x10,%esp
 804b2fc:   01 c6                   add    %eax,%esi
 804b2fe:   3b 5d e4                cmp    -0x1c(%ebp),%ebx
 804b301:   75 ea                   jne    804b2ed <strcpy@plt+0x265d>
 804b303:   8d 65 f4                lea    -0xc(%ebp),%esp
 804b306:   89 f0                   mov    %esi,%eax
 804b308:   5b                      pop    %ebx
 804b309:   5e                      pop    %esi
 804b30a:   5f                      pop    %edi
 804b30b:   5d                      pop    %ebp
 804b30c:   c3                      ret    
 804b30d:   66 90                   xchg   %ax,%ax
 804b30f:   90                      nop
 804b310:   55                      push   %ebp
 804b311:   89 e5                   mov    %esp,%ebp
 804b313:   53                      push   %ebx
 804b314:   bb 04 d0 04 08          mov    $0x804d004,%ebx
 804b319:   52                      push   %edx
 804b31a:   eb 05                   jmp    804b321 <strcpy@plt+0x2691>
 804b31c:   ff d0                   call   *%eax
 804b31e:   83 eb 04                sub    $0x4,%ebx
 804b321:   8b 03                   mov    (%ebx),%eax
 804b323:   83 f8 ff                cmp    $0xffffffff,%eax
 804b326:   75 f4                   jne    804b31c <strcpy@plt+0x268c>
 804b328:   58                      pop    %eax
 804b329:   5b                      pop    %ebx
 804b32a:   5d                      pop    %ebp
 804b32b:   c3                      ret    

Disassembly of section .fini:

0804b32c <_fini>:
 804b32c:   55                      push   %ebp
 804b32d:   89 e5                   mov    %esp,%ebp
 804b32f:   53                      push   %ebx
 804b330:   e8 51 db ff ff          call   8048e86 <strcpy@plt+0x1f6>
 804b335:   81 c3 cb 1d 00 00       add    $0x1dcb,%ebx
 804b33b:   e8 ab db ff ff          call   8048eeb <strcpy@plt+0x25b>
 804b340:   5b                      pop    %ebx
 804b341:   5d                      pop    %ebp
 804b342:   c3                      ret    

ただし、この結果として性能は猛烈に高い。以前chipKit32を比較したときのSketch(List 4)をそのまま実施してみたところ、

Arduino Uno 所要時間約44秒
Galileo 約1秒未満(一瞬)

だった(以前Arduino Unoでは約11秒だったので大分遅くなってるのだが、Arduino IDEのバージョンが大分違うので、おそらくこれが影響しているのではないかと思う。ちなみに今回は1.0.5を利用)。これは81億回の足し算を500回繰り返すものだが、性能面では勝負にならないほどGalileoが高速だった。まぁ16MHz駆動の8bit MCUと400MHz駆動のPentium互換CPUで性能が同じでは話にならないので当然ではあるが、とりあえずArduino IDEで記述したSketchは、仮想マシンなどで動くのではない様である。まぁこれはこれで、ループなどでタイミング調整を行っているSketchでは問題が出てくるかもしれないが。

■ List 4

#define REPEAT  90000
void setup()
{
  pinMode(13, OUTPUT);
}

void loop()
{
  unsigned long  lpCnt1,lpCnt2,lpCnt3;
  unsigned long  num;

  delay(1000);
  digitalWrite(13, HIGH);
  for(lpCnt1=0; lpCnt1<500; lpCnt1++)
  {   
    for(lpCnt2=0; lpCnt2<REPEAT; lpCnt2++)
    {   
      for(lpCnt3=0; lpCnt3<REPEAT; lpCnt3++)
      {   
        num+=lpCnt2+lpCnt3;
      }
    }
  }
  if(num)  digitalWrite(13, LOW);
  else   digitalWrite(13, LOW);
  while(1);
}