H8/3052F をGNU環境でアセンブリする

今年の更新は、H8/3052FをGNU環境でアセンブリすることについて。

研修で、HEWとルネサス純正コンパイラを用いてH8/3048Fを扱った。純正コンパイラは高いので頑張ってGNU環境で出来るようにする。半年前に、どこかのページを参考にして h8300-hms-gcc など環境を整えた。(もうどうやったか覚えてない。cygwin 上で動かしている。)
とりあえず、研修で覚えたアセンブリで動かすことが目標。ボードは秋月電子のH8/3052Fの開発セット。

プログラム本体

; startup.s

	.h8300h

.equ	P5DDR,	0xFFFC8
.equ	P5DR ,	0xFFFCA
.globl	LED
	
	.section .text

LED:	
	mov.l	#0xFFF00, sp
	
	; ポート5 0,1を出力モード
	;bset	#0,	@P5DDR
	;bset	#1, @P5DDR
	
	mov.b	#0x03, r0l
	mov.b	r0l, @P5DDR	

	; LED0,1を点灯
	;bset	#0,	@P5DR
	;bclr	#1, @P5DR
	
	mov.b	r0l, @P5DR
	
EXIT:
	bra		EXIT

	.section .vectors
	.data.l	LED
	
	.END

純正のコンパイラ(?)との違いについて

  • 数値記述法
    • #H'FFFFF が #0xFFFFF
  • EQU文
    • (ラベル: .EQU 数値) が (.equ ラベル, 数値)
  • レジスタ名が小文字限定
  • .global が .globl
    • 嘘でした。ごめなさい。
  • 8ビット絶対アドレス内でもメモリ上のアドレスに対しbsetなどビット演算子が使えないっぽい
  • .section でアドレスの開始指示の仕方が不明
  • .res系が使えない??.byteなどを使うのか?(未確認)

参考: http://akita-nct.jp/~yamamoto/comp/H8/ASM_linux/ASM_linux.html

リンカスクリプト

/* linkerScript.x */
SECTIONS
{
	. = 0x00000;
	.vectors : { *(.vectors) }
	. = 0x00100;
	.text : { *(.text) }
}

初めて自力で書いたので、こんなもん^^;まぁいいかw
参考: http://www.sra.co.jp/wingnut/ld/ld-ja_3.html

Makefile

PROJECT = led
OBJS = startup.o

LINKS = linkerScript.x
LDFLAGS	=	-Xlinker -Map -Xlinker $(PROJECT).map

CC		= h8300-hms-gcc
OBJCOPY	        = h8300-hms-objcopy

$(PROJECT).mot : $(PROJECT).coff
	$(OBJCOPY) -O srec $^ $@

$(PROJECT).coff : $(OBJS)
	$(CC) -o $@ -T $(LINKS) -nostdlib $(OBJS) $(LDFLAGS)

startup.o : startup.s
	$(CC) -c $^
	
clean : 
	rm -f *.o *.mot *.coff

最低限の使い方がわかったので、後は

       *'``・* 。
       |     `*。
      ,。∩      *
     + (´・ω・`) *。+゜  もうどうにでもなーれ
     `*。 ヽ、  つ *゜*
      `・+。*・' ゜⊃ +゜
      ☆   ∪~ 。*゜
      `・+。*・ ゜ 

アドエスでニコニコ動画が観たかったんだ。。

あけましておめでとうございます。今年もよろしく^^たまには更新しようと思いこのページにやってきたら6記事前は2005年に書いたものでした。月日の早さには僕もビックリです。
さて、WillcomAdvanced/W-ZERO3[es] が学生向きに安くなっているので買いました^^色々ソフトをいれて遊んでいるのですが、どうやらニコニコ動画は観れないらしい。。。しょうがないので、少し(ものすごく?)妥協して一度パソコンでみたことあるニコニコ動画の動画をコメントなしでアドエスで見れるようにした^^;一度観たことがある動画をコメントなしで見る価値がどのくらいあるのか、自分でもかなり微妙だけどとりあえず出来たので書いておこう。

  1. nicoCacheを導入してflvファイルをcacheに保存
  2. Orbを導入して動画公開フォルダに上記のcacheを設定
  3. アドエスでアクセスする

以上終わり!細かい説明は省略です。動画配信のエンコード(Orb配信)のところでCPUパワーをたくさん使います。本当は、動画をコメント付で保存することが出来るψ(プサイ)さんの「さきゅばす」というソフトを配信時に挟むと(リアルタイムでコメントを反映させるのは難しいしCPUいっぱい食うだろうけど)それっぽく見せられそうですね。

では、また数ヵ月後にお会いしましょう。

D言語でGnuplot 2

Cygwin用のgdcコンパイルしたものは、実行速度がやけに遅かったので、Windows用バイナリが作成されるようMinGW + gdc をインストールしてみた。こちらでもちゃんと、popen も pclose も使えたのでやっぱり dmd の設定が悪かったのかなぁ。せっかくの機会だったので、Windows上の各コンパイラで作った実行ファイルの実行速度をtimeコマンドを使って測ってみた。このプログラムの内容は、ファイルを読み込み、読み込んだ値をクラスのメンバーに入れたあと、すべてのオブジェクトのあるメンバーにアクセスする、という内容。読み込んだファイルのサイズは約4.5MBのテキスト。

$ time ./WinGdc.exe 

real    0m16.760s
user    0m0.031s
sys     0m0.031s

$ time ./WinDmd.exe 

real    0m16.299s
user    0m0.031s
sys     0m0.031s

$ time ./LinGdc.exe 

real    1m57.082s
user    0m45.484s
sys     1m11.202s

WinGdc.exeはWindowsgdc(MinGWgdc)でコンパイルしたもの。WinDmd.exeはWindowsdmdコンパイルしたもので、LinGdc.exeはCygwingdcを用いてコンパイルしたもの。約8倍速度が違うことがわかる。恐ろしや。。

D言語でgnuplot

前回、ファイルからデータを読み込んで処理を加えることができたので、今度はそれをグラフにしてみることを考える。今までC++を使っていたので、CERNのROOTを読み込んでグラフを作っていたがD言語では使えないので、とりあえずパイプを使ってgnuplotを動かそうとした。C言語でいうpopenとpcloseのようなものを使えばいいが、結論から言ってわからなかった^^;しょうがないから、extern (C) を用いてCのpopenとpcloseを用いることにする。

とりあえず、popenとpcloseが使えるかどうかを確認。

import std.c.stdio;
extern (C) FILE *popen(char *cmd, char *type);
extern (C) int pclose(FILE *fp);

int main(char [][] args)
{
  FILE *gp;
  gp = popen("gnuplot -persist","w");
  fprintf(gp,"plot sin(x)\n");
  pclose(gp);
  return 0;
}

これを、DMD 2.0 Windows版でコンパイルするが、Error 42: Symbol Undefined _popenと_pclose と出てリンクエラー。ここで数日悩む^^;C言語をバイナリは共通とのことなので、Cygwingdcを試すとうまくいった^^;例によってCygwingdcはまだバージョンが古いので公式サイトからCygwin用のgdc最新バージョンを導入する。うまくいくwとりあえずこれ(cygwingdc最新版)でコンパイル自体は上手くいった。X Windowを立ち上げて、実行してみるとgnuplotが立ち上がってsinカーブがちゃんと出てしばし感動w使い方がわかったので、自分の作ったものに組み込んでみると、実行速度が遅い^^;
Windows 上で dmdコンパイルするとある環境では11秒で終了。gdc だと71秒^^;オワタ。。。試しにLinux上でdmdgdcを入れて確認してみると、こちらはどっちも11秒。あぁ、つまりCygwin通してるから遅いのかと納得。よって、Windowsdmd でpopenがきちんと使えるようにすれば多分実行速度が速いであろう。ってなわけで、なぜかWin版dmdで popen がリンク出来ないので設定などを確認してみようと思う。

ファイル出入力

設定ファイルを読み込みパラメータをセッティングするために、ファイルの出入力部分を作ってみた。

ファイルオープン

とりあえず、テスト用 inputFile.dat は以下のような形式だと仮定。

001 North 0x0a
002 South 0x0b
003 East  0x0c
(以下同様).. .. ..

まずは、ファイルオープン。

import std.cstream;
import std.stream;
import std.c.stdio;
import std.string;

int main(char[][] args)
{
  char [] input = "inputFile.dat";
  File fp = new File(input,FileMode.In);

  // process..

  fp.close();
  return 0;
}

引数使えよ。って突っ込みはなしで^^;

読み込み実装1

実際に読み込む部分の実装方法1。foreachを使って読み込んでみる。ファイルの最初から最後まで同じ形式のファイルならばいけるけれど、普通はそんなことないから、実用的ではないかも。

  int i = 0;
  int [] number1,number2;
  char *c_type;
  char [][] direction;
  char [] tmp;
  c_type = toStringz(tmp);
  foreach(char [] line; fp){
    number1.length = number1.length + 1;
    number2.length = number2.length + 1;
    direction.length = direction.length + 1;
    sscanf(toStringz(line),"%d %s 0x%x",&number1[i],c_type,&number2[i]);
    direction[i] = toString(c_type).dup;
    i++;
  }

なぜ、number1.lenght += 1 が使えないのだろう。。。C言語のsscanfと同じような機能をもったD言語の関数を見つけられなかったのでC言語のsscanfを利用。文字列の扱いがC言語D言語で違うためtoString()とtoStringz()を用いてCとDの文字列のやり取りをしている。あと、基本的にD言語の配列のコピーを使いたいときは、.dupをつけないと参照先が同じため一箇所変更を加えると全部変わってしまうので注意。

読み込み実装2

行ごとに読み込むのではなく、1単語ごとに読み込んで処理する。フラグなど立てておけば分岐が出来るのでこっちのほうが色々できそう。

  int i = 0;
  int [] number1,number2;
  char *c_type;
  char [][] direction;
  char [] tmp;
  char [] line;
  c_type = toStringz(tmp);
  
  int mode = 0;
  while(1){
    fp.readf("%s",&line);
    if(fp.eof()) break;
    switch(mode){
    case 0:
      number1.length = number1.length+1;
      sscanf(toStringz(line),"%d",&number1[i]);
      mode++;
      break;
    case 1:
      direction.length = direction.length + 1;
      sscanf(toStringz(line),"%s",c_type);
      direction[i] = toString(c_type).dup;
      mode++;
      break;
    case 2:
      number2.length = number2.length+1;
      sscanf(toStringz(line),"0x%x",&number2[i]);
      mode = 0;
      i++;
      break;
    }
  }

それにしても、もっと上手にやる方法を考えなくては^^;まだ全然わからん^^;

D言語

D言語をやり始めてみた。個人用メモで使っていきます。DMD ver2.0をインストール。cygwinのパッケージのgdcD言語のバージョンが低いのか標準ライブラリにcstreamが入ってなかった。
cygwin上からではdmdがうまく働かないため

cmd /c dmd %1 %2 %3 %4 %5 %6 %7 %8 %9

このようなものをdmd.batなどとパスの通ったところにおいておくとcygwin上からでも無理やりコンパイルできる。

ひさしぶりの更新

ひさしぶりの更新です。というか自分自身、このページ自体にアクセスしたのも久しぶりだよwログイン名とか忘れてしまって悩んでしまった^^;そんなこんなで、こっちも更新してみようと思う。
ところで、こんなに(2年近く)放置していたのに、pvがmixiよりあるのは何故だw