software_development」カテゴリーアーカイブ

赤外線リモコンhack用の機器を積んでいる

最近、iRemoconというのを手に入れた。
これまで他にもいろいろと手に入れて試したり積んだりしている。
最近またいくつか購入してしまった。
1つはIRKitというものだ。
オープンソースでArduinoマイコンで作られている。MFT2013で知った
Rimg0001
IRKit – iPhone,iPadを使って外出先からエアコン等の家電を操作できる学習リモコン(Amazon)
続きを読む

LED照明のリモコンを制御したいのだけど

LED照明のリモコンを制御したいのだけど、これも昨日のエアコンの話で書いたみたいにPCから赤外線リモコンを動かすという形を考えている。
Rimg0001
照明は、AGLED(アグレッド) LEDシーリングライト(LED48W) 【リモコン付】~8畳用 SS-56000というのを使っている。2年前の2013年1月に購入した。
この照明のリモコン制御をiRemoconで学習機能で動かすことができるのは確認した。
続きを読む

スマートフォンで操作する赤外線リモコンiRemocon WiFiを手に入れた

iRemocon WiFiを手に入れた。
当初はNTTのフレッツ契約していてオプションで課金する形でしか使えなかったが、最近一般販売された。
NTT西日本、家電を外出先から制御できるサービスを月額300円で提供開始
グラモ、外出先から家電操作できる据置型リモコン「iRemocon Wi-Fi」販売開始
Rimg0001
iRemocon WiFi(アイリモコンワイファイ) 【外出先から、自宅の家電を操作!快適センサーでお部屋の状況も確認できる学習リモコンの決定版! 】 IRM-03WLA(Amazon)
続きを読む

kmyaccの話

LSI-C(86)やkmyaccの作者の森公一郎氏が亡くなられたそうだ

LSI-C(86)は、試食版ではなくてパッケージ版を持っていた。あとから中古で入手したものだけど。仕舞って保管してあるけど、そろそろ断捨離してもいいだろうか。

kmyaccは、コンパイラ言語の自作とか改造でよく使っていた。

最初にkmyaccを使ったのは学生時代に有限要素法解析に使う計算用モデルのメッシュ生成ソフトでモデル記述言語を自作して構文のパーサーを作るのに使った。MS-DOS上で16bitのプログラミングだったので軽量なkmyaccを使ったのだった。

yaccによるCコンパイラプログラミング」という参考書を参考にしていた。

また、上記の参考書に出てくるC言語のサブセットのコンパイラ言語「Cm」を32bit化する改造にkmyaccの後継バージョンを使っていた。そのとき森公一郎氏と一度だけメールのやりとりをしたのだった。
コンパイラ「Cm」を改造してみる

その後、kmyaccに限定しないで、もっとメジャーなGNU bisonをメインで使うようになったため、kmyaccはあまり使わなくなってしまった。
最近だとbisonを使って.NET(MSIL)やJavaといったVM用中間言語のTiny Basic Compilerを趣味で作ったりしている。
CIL(MSIL)中間コードを生成するTiny BASICコンパイラを作ってみた
Javaバイトコードを生成するTiny BASICコンパイラを作ってみた

近いうちにこのTiny Basic CompilerシリーズのLLVM中間言語版を作ってみようと思っている。

Nexus9をroot化して64bit ARM(AARCH64)のアセンブラを試してみた – まとめ

Nexus9をroot化して64bit ARM(AARCH64)のアセンブラを試してみた。

Nexus9は64bit ARM CPUを搭載しており、いち早く64bit ARM CPU用のソフトを自作して動かすことができる。
とりあえず、単純なHello worldのようなプログラムや、2つの数を加算するだけといったソフトを書いて動かすのを試してみた。

このあたりの情報がこのblog内に散らばっているので、まとめをここに書く。


1. 使ったもの

・Nexus9
・Winddows PC


2. 準備

(1)Neuxus9をroot化する
 → Nexus 9をroot化
(2)Windows PCにNDKをインストールする
 Windows7(64bit版)のPCで、c:\android-ndk-r10dにNDKをインストールした。(NDKは新しいバージョンが出ているので、そのあたりは読み換えで)


3. Hello worldを動かす手順

まず、手始めに簡単はHello worldから動かしてみる。(ここでは、まだアセンブラは使わない)

適当な作業フォルダー(例えば、c:\workなど)を作って、ソースコードを書く。
c:\workの下にjniというフォルダを作成し、そこにソースコードのファイルのhello.cを置く。
hello.c (c:\work\jni\hello.c) の内容は、以下の通り。

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

そして、Android.mkというビルド用の設定を記述したファイル作る。
Android.mk (c:\work\jni\Android.mk) の内容は、以下の通り。

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello
LOCAL_SRC_FILES := hello.c
LOCAL_CFLAGS += -pie -fPIE
LOCAL_LDFLAGS += -pie -fPIE
include $(BUILD_EXECUTABLE)

ビルド用のバッチファイルbuild.batというファイルも作成した。
build.bat (c:\work\build.bat) の内容は以下の通り。

rem =========== environment setting ==========
set PATH=%PATH%;c:\android-ndk-r10d\
set ANDROID_NDK_ROOT=c:\android-ndk-r10d\
set NDK_PROJECT_PATH=.
 
echo =========== 64bit build ============
call ndk-build -B V=1 APP_ABI=arm64-v8a
 
pause

このバッチファイルを実行すると、ソースコードhello.cがビルドされて、64bitのバイナリがc:\work\libsフォルダー以下に生成される。
hello (c:\work\libs\arm64-v8a\hello) が、64ビットのバイナリのファイルだ。

このファイルをNexus9の実機に転送して実行してみた。
Nexus9はroot化したものを使った。
Nexus9の/sdcardフォルダーの直下にtmpというフォルダを作ってそこに一旦helloを転送する。
 

adb push hello /sdcard/tmp/hello

そして、Nexus9側で、
/dataフォルダー直下にtmpというフォルダを作って、そちらにコピーする。
(フォルダーのパーミッション設定が必要だったかも)
 

cp /sdcard/tmp/* /data/tmp

そして、実行するためにchmodコマンドで実行属性を付ける。
 

chmod 744 /data/tmp/hello
そして実行する。

 

/data/tmp/hello
そして実行する。
 
 

64bit
Hello world.

と表示された。

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


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

次に64bit ARMのインラインアセンブラも試してみた。
先ほどと同様の手順で、ソースコード(addvalue.c)は次のように書いた。
アセンブラで2つの数字を加算するというコードだ。

#include <stdio.h>
 
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を使う。

同様にビルドして実行すると、次のようになった。
addvalues = 1234567890123456790
と正しく加算結果が表示された。

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

レジスタ指定の書式は32bit ARMと同じ文法である。この32bit用にビルドしても通ったりする。


5. 直接アセンブラで書いてみる

先程のインラインアセンブラで記述した2つの整数を加算する部分をアセンブラで書き直してみた。

アセンブラ部分のソースコードadd.s (c:\work\jni\add.s)はこのようになった。

   .global addvalues
    .text
    .align 4
addvalues:
    ADD x0,x0,x1;
    ret;

C言語のソース部分(c:\work\jni\addvalue.c)は、以下の通り。

#include <stdio.h>
 
extern long int addvalues(long int, long int);
 
int main(int argc, char **argv, char **envp)
{
  long int val=addvalues(1234567890123456789L,1L);
  printf("addvalues = %ld\n",val);
  return 0;
}

アセンブラで書いたaddvaluesという関数を呼び出している。

Android.mkファイルは、このように設定した。

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := addvalue
LOCAL_SRC_FILES := addvalue.c
LOCAL_SRC_FILES += add.s
LOCAL_CFLAGS += -pie -fPIE
LOCAL_LDFLAGS += -pie -fPIE
include $(BUILD_EXECUTABLE)

-pieと-fPIEのコンパイルオプションの追加は、しなくても64bit ARMのバイナリ生成したものは実機で動作したのだけど、一応念のために追加しておいた。

ビルド手順を記述したバッチファイルのbuild.bat (c:\work\build.bat) の内容は前と一緒で以下の通り。

rem =========== environment setting ==========
set PATH=%PATH%;c:\android-ndk-r10d\
set ANDROID_NDK_ROOT=c:\android-ndk-r10d\
set NDK_PROJECT_PATH=.
  
echo =========== 64bit build ============
call ndk-build -B V=1 APP_ABI=arm64-v8a
  
pause

ソースコードのadd.sについては、32bit ARM用のものを64bit ARM用に書き直して作成した。
加算の部分について
32bit ARM用だと
 

ADD r0,r0,r1;

と書くところを、64bit用に書き直すと以下のようにxレジスタを使う。

ADD x0,x0,x1;

また、関数からのリターン命令を書き直す必要がある。
 

bx lr;

と書くところを、64bit用に書き直すと以下のようにretだけ書けば良い。

ret;

このように書き直して、ビルドしたものは、先程と同様に実機に転送して同じように動作させる。
インラインアセンブラ版のものと同じ動作結果が得られるのが、確認できるはずだ。


6. Hello worldをアセンブラで書きなおす

64bit ARMのアセンブラでHello worldを書くと、このようになった。C言語部分は無くなって、アセンブリのソースコードのみになる。
ソースコード hello.s (c:\work\jni\hello.s)
 

    .global main
    .text
    .align 4
main:
    sub sp,sp,16
    str x30,[sp]
     
    adrp x0,message
    add x0,x0,#:lo12:message
    bl puts
     
    ldr x30,[sp]
    add sp,sp,16
    mov w0,0
 
    ret
 
message:
    .string "Hello world.\n"


Android.mkファイル(c:\work\jni\Android.mk)は次のようになっている。

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello
LOCAL_SRC_FILES := hello.s
LOCAL_CFLAGS += -pie -fPIE
LOCAL_LDFLAGS += -pie -fPIE
include $(BUILD_EXECUTABLE)

build.bat (c:\work\build.bat) の内容は以下の通り。
 

rem =========== environment setting ==========
set PATH=%PATH%;c:\android-ndk-r10d\
set ANDROID_NDK_ROOT=c:\android-ndk-r10d\
set NDK_PROJECT_PATH=.
  
echo =========== 64bit build ============
call ndk-build -B V=1 APP_ABI=arm64-v8a
  
pause

このバッチファイルを実行すれば、ソースコードがビルドされる。

上記のソースコードhello.sは、C言語で記述された
 

puts("Hello world\n");

というコードをgccに-Sオプションを付けてビルドして得られたソース出力ファイルを参考にした。
puts関数を呼び出すのは、
 

bl puts

となる。

putsに渡すパラメータとして文字列”Hello world”を定義したmessageのアドレスをx0レジスタに入れておく必要がある。
 

adrp x0,message
add x0,x0,#:lo12:message

と書く。
32bitのARMと比べるとアドレスを指定するのが面倒になっているらしい。
adrp命令とか「:lo12:」という修飾子がよく分からない。
x86 CPUの8086とかの16bit CPUのSegment+Offsetみたいなものだろうか?


7. Hello worldのコードの修正

64bit ARMアセンブラのHello worldのソースコードをマクロを使って少し書き直してみた。
 

    .global main
    .text
    .align 4
 
    .macro adrl reg,label
    adrp \reg,\label
    add \reg,\reg,:lo12:\label
    .endm
 
main:
    sub sp,sp,16
    str x30,[sp]
     
    adrl x0,message
    bl puts
     
    ldr x30,[sp]
    add sp,sp,16
    mov w0,0
 
    ret
 
message:
    .string "Hello world.\n"

文字列”Hello world”のアドレスmessageをx0レジスタに入れるのに
 

adrp x0,message
add x0,x0,#:lo12:message

と書いていたが、これをadrl疑似命令で記述したかった。
しかし、adrl疑似命令はNDKのアセンブラではサポートされていないので、アセンブラのマクロ機能を使って記述してみた。
 

.macro adrl reg,label
adrp \reg,\label
add \reg,\reg,:lo12:\label
.endm

と、adrl疑似命令をマクロで定義して、

adrl x0,message

このように書くことで、adrp命令とadd命令で2行書いていた部分を簡潔に1行で記述することができる。

Android NDKとNexus9を使って64bit ARMのアセンブラのHello worldを書いてみた その2 

先週の続き

64bit ARMアセンブラのHello worldのソースコードをマクロを使って少し書き直してみた。

	.global main
	.text
	.align 4

	.macro adrl reg,label
	adrp \reg,\label
	add \reg,\reg,:lo12:\label
	.endm

main:
	sub sp,sp,16
	str x30,[sp]
	
	adrl x0,message
	bl puts
	
	ldr x30,[sp]
	add sp,sp,16
	mov w0,0

	ret

message:
	.string "Hello world.\n"

続きを読む

Windowsタブレット用のハコビジョン風のHMDを作ってみた

Windowsタブレット用のハコビジョン風のHMDを作ってみた。

以前、ハコスコ風のWindowsタブレット用HMDを自作し、カメラを使ったARアプリでAR電卓とかを動かして使っていた。

AR(拡張現実)用に使うのに透過型HMDの方式もやってみたいと考えていて、ハコビジョンみたいな感じに上にタブレットを乗っけて作れるのではないかと前々から考えていた。
軽量な中華Windowsタブレットを手に入れたので、これに合わせて作ってみようと思い、材料を探して集めていた。
材料のハーフミラーが手に入ったので、とりあえずダンボールでそれっぽいものを組み立ててみた。
Rimg0005
前に作ったハコスコ風のものを比べるとこんな感じ。
続きを読む

Android NDKとNexus9を使って64bit ARMのアセンブラのHello worldを書いてみた 

今日は、Android NDKとNexus9を使って64bit ARMのアセンブラのHello worldを書いてみた。

昨日の続きだ。
Android NDKとNexus9を使って64bit ARMのアセンブラを試してみた

64bit ARMのアセンブラでHello worldを書くと、このようになった。
ソースコード hello.s (c:\work\jni\hello.s)

	.global main
	.text
	.align 4
main:
	sub sp,sp,16
	str x30,[sp]
	
	adrp x0,message
	add x0,x0,#:lo12:message
	bl puts
	
	ldr x30,[sp]
	add sp,sp,16
	mov w0,0

	ret

message:
	.string "Hello world.\n"

続きを読む