AKI-
H8/3048foneのモニタプログラム,クロスアセンブラ環境での
アセンブリ言語プログラミング
Copyright(C)12Mar2014
since 1Aug2003
coskx
1.はじめに
この文書は,AKI-H8におけるH8/3048foneのモニタプログラム,PCターミナルソフトで の学習を記述している。
モニタプログラムは,新しいプログラムの動作を検証する場合や,アセンブリ言語の学習者が,1命令ずつ機械語命令を実行してCPUのふるまいを観察するプ ログラムである。モニタプログラムはROM(フラッシュメモリ)上に配置されており,検証対象のプログラムはRAM上に置かれる。
この文書では
(1)PC上のエディタでアセンブリ言語プログラムを作成し,アセンブラに機械語プログラムに変換
(2)マイコンではモニタプログラムを動作させ,ターミナル画面から機械語プログラムをマイクロコンピュータに転送
(3)モニタプログラム上でこのプログラムを動作させる
手順を解説します。(本校)校内からは授業に使うため準備用ファイルが入手できます。またマニュアルもダウンロードしておくとよい。
このファイルを解凍すると「trial5」のフォルダが出てくるので,
作業用フォルダとして使う。
((本校)LANからのみ試用のためアクセスできる。)
(4J電子計算機IIの授業ではこれを使う)
H8機械語命令ニモニックの説明マニュアル
((本校)LANからのみアクセスできる。)
基本事項 再掲
レジスタは32ビット幅で8個あり,名前はER0,ER1,ER2,ER3,ER4,ER5,ER6,ER7である。
またER0は,2つの16ビット幅レジスタE0,R0として使うこともできる。
(従って,R0とER0を同時に別の用途に使うことはできない)
さらにまた16ビット幅レジスタR0は,2つの8ビット幅のレジスタR0H,R0Lとして使うこともできる。
(従って,R0LとR0やER0を同時に別の用途に使うことはできない)
または
ER0 (32bit)
または
E0 (16bit)
R0 (16bit)
レジスタER0の構造と使われ方
E0 (16bit)
R0H (8bit)
R0L (8bit)
ER0の構造はER1,ER2,ER3,ER4,ER5,ER6でも同じである。
例えばER1では次のようになっている
または
ER1 (32bit)
または
E1 (16bit)
R1 (16bit)
レジスタER1の構造と使われ方
E1 (16bit)
R1H (8bit)
R1L (8bit)
もう一例を上げれば,ER2では次のようになっている
または
ER2 (32bit)
または
E2 (16bit)
R2 (16bit)
レジスタER2の構造と使われ方
E2 (16bit)
R2H (8bit)
R2L (8bit)
bit,byteと16進表示についてまとめておこう
ビット数
バイト数
16進表現桁数
表現範囲
略号
バイト
8bit
1byte
2桁
00-FF
B
ワード
16bit
2byte
4桁
0000-FFFF
W
ロングワード
32bit
4byte
8桁
00000000-FFFFFFFF
L
2.アセンブリ言語プログラムをエディタで作成し,アセンブルを行い,モニタ上で実行
モニタプログラム上で1行ずつ命令を直打ちしてアッセンブルできるとは言っても,そのまま数十行のプログラムを書くことは現実的ではない。
そこで,アセンブリ言語で書かれたソースプログラムを,汎用エディタ(たとえばTeraPad)で作成し,アセンブルし,リンク,コンバー ト(モトローラS 形式にするとフラッシュメモリ書き込み可能となる)して,.MOTファイルを作って,これまでと同様に1ステップずつ実行してみる。
ただし,通常はROM領域に配置されるプログラムを,RAM領域に置く。
(1)アセンブリ言語で書かれたプログラム例
プログラムは次のようなものである。
スタックポインタを初期化する(使わないのでしなくてもよい)
FF800番地の2byteデータをレジスタR0に載せる
FF802番地の2byteデータをレジスタR1に載せる
R0とR1の値を加えてR0にしまう
R0のデータをFF804番地にしまう
作業が終了したので無限ループに入る(OSなしのマイコンのプログラムは終わることが出来ない)
ただしプログラム起動の時点で,
FF800番地にはx1234,FF802番地にはx2345,FF804番地にはx3456が入っているものとする。
アセンブリプログラムのしきたり
・先頭が「.」で始まる行は,機械語に翻訳される命令ではなく,コンパイラに対して
指示を与える擬似命令と呼ばれるものである。
・行の1文字目から始まり「:」で終わる行は,ラベルといって機械語に翻訳はされず,
機械語ではアドレスに解釈される。
例えば「EternalLoop:」はBRA EternalLoopのジャンプ命令の行き先であり,
「data1:」はff800を,「data2:」はff802を「data3:」はff804を意味している。
モニタ上で命令を直打ちするよりも,アドレス指定はラベルが使えるため,便利に
なっている。。
・命令および擬似命令を書く時は,行頭は少なくとも1つのスペースかあるいはタブ
で始まらなければならない。ここでは4つのスペースを使っている
test.src
ソースプログラムのダウンロード
右クリックでダウンロードしてください
.CPU 300HA
.SECTION A,DATA,LOCATE=H'0FF030
.DATA.L H'0FF130 ;リセットベクトル
.SECTION P,CODE,LOCATE=H'0FF130
MOV.L #H'FFF00,ER7 ;スタックポインタ設定
MOV.W @data1, r0 ;data1にある値をレジスタr0へ
MOV.W @data2, r1 ;data2にある値をレジスタr1へ
ADD.W r1,r0 ;レジスタr0+r1→r0
MOV.W r0,@data3 ;レジスタr0にある値をdata3へ
EternalLoop:
BRA EternalLoop ;永久ループ
.SECTION D,DATA,LOCATE=H'0FF800
data1:
.DATA.W H'1234
data2:
.DATA.W H'2345
data3:
.DATA.W H'3456
.END対象CPU群名
ベクタテーブル領域 0FF030から
プログラム領域0FF130から
終端処理(無限ループ)
データ領域0FF800から
2バイトデータ 1234
2バイトデータ 2345
2バイトデータ 3456H8 命令ニーモニクの説明マニュアル 学内高速読み取りバッファより
(2)アセンブルからコンバートまで
「test.src」を「Asm2Mon.cmd」にドラッグ&ドロップします。フラッシュメモリ書き込み形式ファイル「test.MOT」 ができます。
この「Asm2Mon.cmd」を使用するとソースリストファイル「test.LIS」とマップファイル「test.MAP」も出来ます。
test.LIS
アドレスとプログラムソースの対応を見ると,FF130からFF14Aまでにプログラムがあることがわかる。
ラベル(例えば「data1:」)はただのアドレスとして扱われていることも判る。
** H8S,H8/300 ASSEMBLER Ver.2.0A Evaluation software ** 08/01/03 22:16:40 PAGE 1
Address Instruction ProgramSource
1 1 .CPU 300HA
2 0FF030 2 .SECTION A,DATA,LOCATE=H'0FF030
3 0FF030 000FF130 3 .DATA.L H'0FF130 ;リセットベクトル
4 4
5 0FF130 5 .SECTION P,CODE,LOCATE=H'0FF130
6 0FF130 7A07000FFF00 6 MOV.L #H'FFF00,ER7 ;スタックポインタ設定
7 0FF136 6B20000FF800 7 MOV.W @data1, r0 ;data1にある値をレジスタr0へ
8 0FF13C 6B21000FF802 8 MOV.W @data2, r1 ;data2にある値をレジスタr1へ
9 0FF142 0910 9 ADD.W r1,r0 ;レジスタr0+r1→r0
10 0FF144 6BA0000FF804 10 MOV.W r0,@data3 ;レジスタr0にある値をdata3へ
11 0FF14A 11 EternalLoop:
12 0FF14A 40FE 12 BRA EternalLoop ;永久ループ
13 13
14 0FF800 14 .SECTION D,DATA,LOCATE=H'0FF800
15 0FF800 15 data1:
16 0FF800 1234 16 .DATA.W H'1234
17 0FF802 17 data2:
18 0FF802 2345 18 .DATA.W H'2345
19 0FF804 19 data3:
20 0FF804 3456 20 .DATA.W H'3456
21 21
22 22 .END
*****TOTAL ERRORS 0
*****TOTAL WARNINGS 0
** H8S,H8/300 ASSEMBLER Ver.2.0A Evaluation software ** 08/01/03 22:16:40 PAGE 2
*** CROSS REFERENCE LIST
NAME SECTION ATTR VALUE SEQUENCE
A A SCT 000FF030 2*
D D SCT 000FF800 14*
EternalLoop P 000FF14A 11* 12
P P SCT 000FF130 5*
data1 D 000FF800 7 15*
data2 D 000FF802 8 17*
data3 D 000FF804 10 19*
** H8S,H8/300 ASSEMBLER Ver.2.0A Evaluation software ** 08/01/03 22:16:40 PAGE 3
*** SECTION DATA LIST
SECTION ATTRIBUTE SIZE START
A ABS-DATA 0000004 0FF030
P ABS-CODE 000001C 0FF130
D ABS-DATA 0000006 0FF800
test.MAP
H SERIES LINKAGE EDITOR Ver. 5.3B
LINK COMMAND LINE
LNK test -PRINT=test
H SERIES LINKAGE EDITOR Ver. 5.3B PAGE : 1
*** LINKAGE EDITOR LINK MAP LIST ***
SECTION NAME START - END LENGTH UNIT NAME MODULE NAME
ATTRIBUTE : DATA NOSHR
A H'000FF030 - H'000FF033 H'00000004 test test
* TOTAL ADDRESS * H'000FF030 - H'000FF033 H'00000004
ATTRIBUTE : CODE NOSHR
P H'000FF130 - H'000FF14B H'0000001C test test
* TOTAL ADDRESS * H'000FF130 - H'000FF14B H'0000001C
ATTRIBUTE : DATA NOSHR
D H'000FF800 - H'000FF805 H'00000006 test test
* TOTAL ADDRESS * H'000FF800 - H'000FF805 H'00000006(3)RAM書き込み
ここでH8CPUのRAM領域へのプログラム書き込みを行う。
この作業の前に,モニタプログラム「MONITOR3048fone.MOT」 の転送(ROM領域への書き込み)が行われている必要がある。
(一度モニタプログラムがROM領域にかきこまれたなら,RAM領域への書き込みは何回でもできる)
RAM領域への書き込みでは,モニタプログラムをRUNモードで動かしておく必要がある
teratermを用いた機械語プログラムの転送 ハイパーターミナルを用いた機械語プログラムの転送 1)AKI-H8側はモニタプログラムがRUNしている状態にしておく。
2)PCではteratermを起動する。3)teraterm上で「L」コマンドを与える。
("L"+"Enter")
この時のモニタ画面
: L
そのままにしておく
4)転送したいxxxx.motのアイコンをteratermモニタ画面に
ドロップして,出てきたメニューでファイル送信を選ぶ。
別の方法
teratermの「ファイル」メニューの
「ファイル送信」コマンドを実行する。
ファイルセレクタが出てくるので,
ファイルの種類を「*.*」にして「test.MOT」を選択する。5)書き込み終了(数秒待つと次のように表示される)
RAM書き込み終了時のモニタ画面 : L
Top Address=FF030
End Address=FF805
:
1)AKI-H8側はモニタプログラムがRUNしている状態にしておく。
2)PCではハイパーターミナルを起動する。3)ハイパーターミナル上で「L」コマンドを与える。
("L"+"Enter")
この時のモニタ画面
: L
そのままにしておく
4)ハイパーターミナルの「転送」メニューの
「テキストファイルの送信」コマンドを実行する。
ファイルセレクタが出てくるので,
ファイルの種類を「*.*」にして「test.MOT」を選択する。5)書き込み終了(数秒待つと次のように表示される)
RAM書き込み終了時のモニタ画面 : L
Top Address=FF030
End Address=FF805
:
(4)実行前の確認
フラッシュメモリ書き込みが終了したら,以下のようにff800番地とff130番地のところに
test.srcの変数データとプログラムが正常にダウンロードされたことを確かめよう。プログラムソースのラベルが数値のアドレスに変換されたこともわかる。
(例えば「 MOV.W @data1, r0」は「 MOV.W @H'FF800:24,R0」になっている)
内容 モニタ画面 ff800番地付近の
メモリ表示: d ff800 ff80f
<ADDR> < D A T A > < ASCII CODE >
FF800 12 34 23 45 34 56 DB 7B E2 8C E7 5B 04 80 E7 7A ".4#E4V.{...[...z"プログラムの確認
(ディスアセンブル)
2.(2)において
プログラムの末尾
がff14aであること
が読み取れていた。
: da ff130 ff14a
FF130 7A07000FFF00 MOV.L #H'000FFF00:32,ER7
FF136 6B20000FF800 MOV.W @H'FF800:24,R0
FF13C 6B21000FF802 MOV.W @H'FF802:24,R1
FF142 0910 ADD.W R1,R0
FF144 6BA0000FF804 MOV.W R0,@H'FF804:24
FF14A 40FE BRA FF14A:8(5)実行
1ステップずつ実行します。
内容 モニタ画面 レジスタの確認 : r
PC=0FF11A CCR=80:I....... SP=000FFF10
ER0=00000000 ER1=00000000 ER2=00000000 ER3=00000000
ER4=00000000 ER5=00000000 ER6=00000000 ER7=000FFF10プログラムカウン
タ(PC)にスター
トすべき先頭アド
レスをセット*1: .pc
PC=0FF11A ? 0ff130
CCR=80 ? .レジスタの確認 : r
PC=0FF130 CCR=80:I....... SP=00FFFF10
ER0=00000000 ER1=00000000 ER2=00000000 ER3=00000000
ER4=00000000 ER5=00000000 ER6=00000000 ER7=00FFFF101ステップずつ
実行: s
PC=0FF136 CCR=80:I....... SP=000FFF00
ER0=00000000 ER1=00000000 ER2=00000000 ER3=00000000
ER4=00000000 ER5=00000000 ER6=00000000 ER7=000FFF00
FF130 7A07000FFF00 MOV.L #H'000FFF00:32,ER7
: s
PC=0FF13C CCR=80:I....... SP=000FFF00
ER0=00001234 ER1=00000000 ER2=00000000 ER3=00000000
ER4=00000000 ER5=00000000 ER6=00000000 ER7=000FFF00
FF136 6B20000FF800 MOV.W @H'FF800:24,R0
: s
PC=0FF142 CCR=80:I....... SP=000FFF00
ER0=00001234 ER1=00002345 ER2=00000000 ER3=00000000
ER4=00000000 ER5=00000000 ER6=00000000 ER7=000FFF00
FF13C 6B21000FF802 MOV.W @H'FF802:24,R1
: s
PC=0FF144 CCR=80:I....... SP=000FFF00
ER0=00003579 ER1=00002345 ER2=00000000 ER3=00000000
ER4=00000000 ER5=00000000 ER6=00000000 ER7=000FFF00
FF142 0910 ADD.W R1,R0
: s
PC=0FF14A CCR=80:I....... SP=000FFF00
ER0=00003579 ER1=00002345 ER2=00000000 ER3=00000000
ER4=00000000 ER5=00000000 ER6=00000000 ER7=000FFF00
FF144 6BA0000FF804 MOV.W R0,@H'FF804:24
:ff800番地
付近のメモリ
表示 *2
: d ff800 ff80f
<ADDR> < D A T A > < ASCII CODE >
FF800 12 34 23 45 35 79 DB 7B E2 8C E7 5B 04 80 E7 7A ".4#E5y.{...[...z"*1 直前のレジスタ確認で,プログラムカウンタPCがFF130になっているときはこの作業は不要である。
*2 プログラム実行前のメモリ内容表示と比較するとプログラムが意図したとおりに動作したことが判る。
3.プログラムのブレークポイントまでの実行
2.(1)~(3)によってプログラムがすでに書き込まれているとして,FF14Aにブレークポインタ
(ここまで実行されたら,止まってモニタに制御を戻せというしるし)を設定し,プログラム先頭から
ブレーク ポインタまでを一気に動作させる。(1)実行前の確認
以下のようにff800番地付近にデータが,ff130番地のところにプログラムが存在することを確かめよう。
和が格納されるべきアドレス FF804に実行後に和が格納されることを確かめられるように,mコマンドで
適当な値に変更しておくとよい。
内容 モニタ画面 ff800番地付近の
メモリ表示: d ff800 ff80f
<ADDR> < D A T A > < ASCII CODE >
FF800 12 34 23 45 00 00 DB 7B E2 8C E7 5B 04 80 E7 7A ".4#E...{...[...z"プログラムの確認
(ディスアセンブル)
2.(2)において
プログラムの末尾
がff14aであること
が読み取れていた。
: da ff130 ff14a
FF130 7A07000FFF00 MOV.L #H'000FFF00:32,ER7
FF136 6B20000FF800 MOV.W @H'FF800:24,R0
FF13C 6B21000FF802 MOV.W @H'FF802:24,R1
FF142 0910 ADD.W R1,R0
FF144 6BA0000FF804 MOV.W R0,@H'FF804:24
FF14A 40FE BRA FF14A:8(2)実行
ブレークポインタを設定して実行します。
内容 モニタ画面 レジスタの確認 : r
PC=0FF11A CCR=80:I....... SP=000FFF10
ER0=00000000 ER1=00000000 ER2=00000000 ER3=00000000
ER4=00000000 ER5=00000000 ER6=00000000 ER7=000FFF10プログラムカウンタ
(PC)の変更
*1: .pc
PC=0FF11A ? 0ff130
CCR=80 ? .レジスタの確認 : r
PC=0FF130 CCR=80:I....... SP=00FFFF10
ER0=00000000 ER1=00000000 ER2=00000000 ER3=00000000
ER4=00000000 ER5=00000000 ER6=00000000 ER7=00FFFF10ブレークポインタ
の設定
2.(2)において
プログラムの末尾
がff14aであること
が読み取れていた。
: b ff14a
現在のプログラム
カウンタのアドレスから
ブレークポインタまで
実行: g
Break at PC=FF14A
PC=0FF14A CCR=80:I....... SP=000FFF00
ER0=00003579 ER1=00002345 ER2=00000000 ER3=00000000
ER4=00000000 ER5=00000000 ER6=00000000 ER7=000FFF00ff800番地付近の
メモリ表示
: d ff800 ff80f
<ADDR> < D A T A > < ASCII CODE >
FF800 12 34 23 45 35 79 DB 7B E2 8C E7 5B 04 80 E7 7A ".4#E5y.{...[...z"*1 すでにプログラムカウンタPCがFF130になっているときはこの作業は不要です。
注意 もしブレークポインタをセットせずにgコマンドで起動すると,そのまま
BRA FF14A:8
のところで無限ループに突入するため,モニタのコマンドを受け付けなくなってしまう。
このような場合には,H8の電源を落とすしかない。
参考 プログラムの工夫とGコマンドの工夫によって手間を省く
(1)プログラムの終端に自分自身へのジャンプ命令を置いて無限ループを作る代わりに,モニタの先頭アド レスへジャンプさせてモニタを再起動させてもメモリの内容は変化しないので,プログラムの終端をモニタの先頭アドレスへジャンプするように変更する。この ようにすると,モニタ内でプログラム終端でモニタに制御を戻すためのブレークポインタの設定は不要になる。
(2)Gコマンドは,起動アドレスも指示できるので,PCへの操作を省くことができる。
EQU擬似命令はC言語の#defineと同じ働きをする。プログラム本体に「RESTART」が出てきたら,それは「H'100」としてアセンブルしなさいの意味である。
ゆえに,JMP @RESTART は JMP @H'100 とおなじであり,「アドレス0x100にジャンプしなさい」の意味になる。
(0x100はモニタの先頭アドレス(=モニタの起動アドレス))
test1.src
ソースプログラムのダウンロード
右クリックでダウンロードしてください
.CPU 300HA
RESTART .EQU H'100 ;モニタの先頭アドレス
.SECTION A,DATA,LOCATE=H'0FF030
.DATA.L H'0FF130 ;リセットベクトル
.SECTION P,CODE,LOCATE=H'0FF130
MOV.L #H'FFF00,ER7 ;スタックポインタ設定
MOV.W @data1, r0 ;data1にある値をレジスタr0へ
MOV.W @data2, r1 ;data2にある値をレジスタr1へ
ADD.W r1,r0 ;レジスタr0+r1→r0
MOV.W r0,@data3 ;レジスタr0にある値をdata3へ
JMP @RESTART ;モニターに戻る
.SECTION D,DATA,LOCATE=H'0FF800
data1:
.DATA.W H'1234
data2:
.DATA.W H'2345
data3:
.DATA.W H'3456
.END
ベクタテーブル領域 0FF030から
プログラム領域0FF130から
データ領域0FF800から
2バイトデータ 1234
2バイトデータ 2345
2バイトデータ 3456
実行の様子モニタが再起動しているのがわかる。
: l
Top Address=FF030
End Address=FF805
: da ff130 ff14a
<ADDR> <CODE> <MNEMONIC> <OPERAND>
FF130 7A07000FFF00 MOV.L #H'000FFF00:32,ER7
FF136 6B20000FF800 MOV.W @H'FF800:24,R0
FF13C 6B21000FF802 MOV.W @H'FF802:24,R1
FF142 0910 ADD.W R1,R0
FF144 6BA0000FF804 MOV.W R0,@H'FF804:24
FF14A 5A000100 JMP @H'00100:24
: d ff800 ff80f
<ADDR> < D A T A > < ASCII CODE >
FF800 12 34 23 45 34 56 FF FF DF EC FD FF FF FF FF FF ".4#E4V.........."
: g ff130
H8/3048 Series Advanced Mode Monitor Ver. 3.0A
Copyright (C) 2003 Renesas Technology Corp.
: d ff800 ff80f
<ADDR> < D A T A > < ASCII CODE >
FF800 12 34 23 45 35 79 FF FF DF EC FD FF FF FF FF FF ".4#E5y.........."
:
4. メモリ領域のフィル
メモリの指定された領域(アドレス◯◯からアドレス□□まで)を,ある値で埋め尽くします。
実際には,メモリ上の指定されたアドレスから順番に,埋めるべき値を書き込んでいきます。
そして必要なバイト数だけ作業したら終了します。
モニタコマンド f(fill) について
例題1 アセンブラを用いて次のプログラムを作成しなさい。
(FF200から機械語プログラムを置きなさい。)
FF800番地 - FF83F番地メモリすべてに0x55を埋めるプログラム。以下を報告しなさい。
実行前のFF800番地 - FF83F番地のメモリ表示
プログラムの逆アッセンブル結果
ブレークポイントを設定して実行した時の実行の様子
実行後のFF800番地 - FF83F番地のメモリ表示
(実行前のメモリ表示と比較して,意図した動作ができているかどうか確かめる)プログラムの
概要
メモリのある領域を1バイトのデータで埋めるためには,次のようにすればよい。
◯使用するレジスタ
(1)値を埋めるアドレスを保管するレジスタA(最低24ビット必要)
(2)埋める値を保管する1バイトのレジスタB
(3)埋めた数を数えるレジスタC
(ここでは40(Hex)個数えれば良いので1バイトのレジスタで足りる)
(ダウンカウントで数えて,繰り返し作業の終了を判断する)
◯作業手順
(1)レジスタAに作業対象先頭アドレスを設定
(2)レジスタBに埋めるべき値を設定
(3)レジスタCに埋める個数を設定
(4)レジスタAの指しているアドレスにレジスタBの値を保存
(5)レジスタAの値を1増やす
(6)レジスタCの値を1減らす
(7)レジスタCの値が0になっていなかったら(4)に戻る
レジスタA,B,Cはプログラムでは実在するレジスタを割り当てる。
アセンブリ
プログラム
testfill.src
ソースプログ
ラムの
ダウンロード
右クリック
でダウンロ
ードしてく
ださい
青字:レジスタ
初期設定
紫字:作業ル
ープ
.CPU 300HA
.SECTION A,DATA,LOCATE=H'0FF030
.DATA.L H'0FF200 ;リセットベクトル.SECTION P,CODE,LOCATE=H'0FF200
MOV.L #H'FFF00,ER7 ;スタックポインタ設定
MOV.L #area,ER1 ;作業対象先頭アドレスをレジスタer1へ
MOV.B #H'55, r0l ;埋める値0x55をレジスタr0lへ
MOV.B #H'40, r0h ;埋める個数0x40をレジスタr0h
L001:
MOV.B r0l,@ER1 ;0x55をER1の指しているところへ
INC.L #1,ER1 ;ER1を1増やす(32bit操作)
DEC.B r0h ;R0Hを1減らす(8bit操作)
BNE L001:8 ; r0h!=0の場合はL001へジャンプ
EternalLoop:
BRA EternalLoop ;永久ループ.SECTION D,DATA,LOCATE=H'0FF800 ;データ領域0FF800から
area:
.res.b H'40 ;40バイトの領域を確保 先頭アドレスはFF800になる
.END
プログラムの
補足説明
行の1文字目から書かれる名前はラベルと呼ばれ,ジャンプ命令の行き先となる。
(ラベルは,機械語に変換されるとアドレスになる。)
「BNE L001:8」 直前の操作の結果が0でなかったら,L001にジャンプする
(Branch Not Equal to 0)
ある条件が成り立ったらジャンプするという命令は条件ジャンプと呼ばれ,
C言語でいうところのif文の構造を作ったり,ループ構造を作ったりするのに
必須の命令である。
条件ジャンプ(条件ブランチ)は多くの種類があるため,命令マニュアルでは
「Bcc」として一括して説明されている。ファイルの
準備
アセンブルして,testfill.srcからtestfill.MOTを作成する。
このときtestfill.LISもできるので,.LISファイルをエディタで開いて
プログラムの最終アドレスを読み取っておく必要がある。
そうしないと逆アセンブルする時,プログラムの最終アドレスがわからなくなる。
ここでは0FF218が読み取れるはずである。
RAM領域へ
プログラムを
転送
逆アセンブル
してプログラ
ムを確認
作業範囲の
メモリを確認
fコマンドで
ff800-ff84fを
aaで埋めておく
作業範囲の
メモリを確認
AAが埋められた
ブレークポイ
ントの設定
実行
メモリの状態を
実行前と実行後
を比べて,意図
した作業ができ
ているかどうか
検証している
: l
Top Address=FF030
End Address=FF219
: da ff200 ff219
<ADDR> <CODE> <MNEMONIC> <OPERAND>
FF200 7A07000FFF00 MOV.L #H'000FFF00:32,ER7
FF206 7A01000FF800 MOV.L #H'000FF800:32,ER1
FF20C F855 MOV.B #H'55:8,R0L
FF20E F040 MOV.B #H'40:8,R0H
FF210 6898 MOV.B R0L,@ER1
FF212 0B71 INC.L #1,ER1
FF214 1A00 DEC.B R0H
FF216 46F8 BNE FF210:8
FF218 40FE BRA FF218:8
: d ff800 ff85f
<ADDR> < D A T A > < ASCII CODE >
FF800 FF FF 7F DF FF FF FF FF DF EC FD FF FF FF FF FF "................"
FF810 FF FF EF F3 FF AF FF F7 FF EB DE F7 FF FF FF FF "................"
FF820 DF FF FF FF FF BF FB FF AF DF DF FF BF FB FF FF "................"
FF830 FF F9 7E EF FF DC BF DB FA FF FF FF 9D FF FD FF "..~............."
FF840 FF FF FF FF FF DF DF FF FF FF 7F FF FF F7 BE FF "................"
FF850 6F FF FF E7 FF FF DF FF 97 F7 FA FF BE F3 FF 27 "o..............'"
: f ff800 ff84f aa
: d ff800 ff85f
<ADDR> < D A T A > < ASCII CODE >
FF800 AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA "................"
FF810 AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA "................"
FF820 AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA "................"
FF830 AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA "................"
FF840 AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA "................"
FF850 6F FF FF E7 FF FF DF FF 97 F7 FA FF BE F3 FF 27 "o..............'"
: .pc
PC=0FF200 ? ff200
CCR=80 ? .
: b ff218
: r
PC=0FF200 CCR=80:I....... SP=000FFF00
ER0=00000000 ER1=00000000 ER2=00000000 ER3=00000000
ER4=00000000 ER5=00000000 ER6=00000000 ER7=000FFF00
: g
Break at PC=FF218
PC=0FF218 CCR=84:I....Z.. SP=000FFF00
ER0=00000055 ER1=000FF840 ER2=00000000 ER3=00000000
ER4=00000000 ER5=00000000 ER6=00000000 ER7=000FFF00
: d ff800 ff84f
<ADDR> < D A T A > < ASCII CODE >
FF800 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 "UUUUUUUUUUUUUUUU"
FF810 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 "UUUUUUUUUUUUUUUU"
FF820 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 "UUUUUUUUUUUUUUUU"
FF830 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 "UUUUUUUUUUUUUUUU"
FF840 AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA "................"
:
上記の実行中で 「f ff800 ff84f aa」という命令を行なっている,
これは,メモリのff800からff84fまでをaaで埋めるという命令である。
作成したフィルプログラムが正しく動作したかどうかどうかを検証するためには,
予め検証が可能なように,少し余計な範囲まで,異なる値を埋めておく必要がある。
(プログラムのミスで意図した領域を超えて値を埋めてしまうことがあるため)
H8
命令ニーモニクの説明マニュアル 学内高速読み取りバッファより
課題4.1 |
テキストエディタとアセンブラを用いて次のプログラムを作成しなさい。 実行前のFF800番地 - FFA0F番地の様子 ヒント 8bitのレジスタの扱うことのできる値の範囲は0 - 255 |
5. メモリ領域のブロック転送
メモリの特定の領域を,別の領域にまるごとコピーする。
例題1 |
アセンブラを用いて次のプログラムを作成しなさい。
以下を報告しなさい。 |
プログラムの 概要 |
ブロック転送の考え方 ◯使用するレジスタ
◯作業手順 レジスタA,B,C,Dはプログラムでは実在するレジスタを割り当てる。 |
アセンブリ プログラム testmove.src ソースプログ ラムの ダウンロード 右クリック でダウンロ ードしてく ださい 青字:レジスタ 初期設定 紫字:作業ル ープ |
.CPU 300HA |
ファイルの 準備 |
アセンブルして,testmove.srcからtestmove.MOTを作成する。 このときtestmove.LISもできるので,.LISファイルをエディタで開いて プログラムの最終アドレスを読み取っておく必要がある。 そうしないと逆アセンブルする時,プログラムの最終アドレスがわからなくなる。 ここでは0FF220が読み取れるはずである。 |
RAM領域へ プログラムを 転送 逆アセンブル して,プログ ラムを確認 作業範囲の メモリを確認 fコマンドで ff800-ff84fを aaで埋めておく 作業範囲の メモリを確認 AAが埋められた コピー元の 確認 ブレークポイ ントの設定 実行 メモリの状態を 実行前と実行後 を比べて,意図 した作業ができ ているかどうか 検証している |
: L Top Address=FF030 End Address=FF221 : da ff200 ff221 <ADDR> <CODE> <MNEMONIC> <OPERAND> FF200 7A07000FFF00 MOV.L #H'000FFF00:32,ER7 FF206 7A0100000000 MOV.L #H'00000000:32,ER1 FF20C 7A02000FF800 MOV.L #H'000FF800:32,ER2 FF212 F040 MOV.B #H'40:8,R0H FF214 6818 MOV.B @ER1,R0L FF216 68A8 MOV.B R0L,@ER2 FF218 0B71 INC.L #1,ER1 FF21A 0B72 INC.L #1,ER2 FF21C 1A00 DEC.B R0H FF21E 46F4 BNE FF214:8 FF220 40FE BRA FF220:8 : d ff800 ff85f <ADDR> < D A T A > < ASCII CODE > FF800 FF FF 7F DF FF FF FF DF DF EC F5 FF FF FF FF FF "................" FF810 FF FF EF F3 FF BF FE F7 FF EB DE F7 FF FF FF FF "................" FF820 DF FF FF FF FF BF FB FF AF DF DF FF BF FA FF FF "................" FF830 FF FD 7E EF FB DE BF DB FA FF FF FF 9D FF FD FF "..~............." FF840 FF FF FF FF FF DF DF FF FF FF 7F FF FF F7 BE FF "................" FF850 6F FE FF E7 FF FF DF FF 97 FF FA FF BE F3 FF 27 "o..............'" : f ff800 ff84f aa : d ff800 ff85f <ADDR> < D A T A > < ASCII CODE > FF800 AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA "................" FF810 AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA "................" FF820 AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA "................" FF830 AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA "................" FF840 AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA "................" FF850 6F FE FF E7 FF FF DF FF 97 FF FA FF BE F3 FF 27 "o..............'" : d 0 4f <ADDR> < D A T A > < ASCII CODE > 00000 00 00 01 00 00 00 28 16 00 00 28 1A 00 00 28 1E "......(...(...(." 00010 00 00 28 22 00 00 28 26 00 00 28 2A 00 00 28 2E "..("..(&..(*..(." 00020 00 00 28 32 00 00 28 36 00 00 28 3A 00 00 28 3E "..(2..(6..(:..(>" 00030 00 00 28 42 00 00 28 46 00 00 28 4A 00 00 28 4E "..(B..(F..(J..(N" 00040 00 00 28 52 00 00 28 56 00 00 28 5A 00 00 28 5E "..(R..(V..(Z..(^" : .pc PC=0FF200 ? ff200 CCR=80 ? . : b ff220 : r PC=0FF200 CCR=80:I....... SP=000FFF00 ER0=00000000 ER1=00000000 ER2=00000000 ER3=00000000 ER4=00000000 ER5=00000000 ER6=00000000 ER7=000FFF00 : g Break at PC=FF220 PC=0FF220 CCR=84:I....Z.. SP=000FFF00 ER0=0000004E ER1=00000040 ER2=000FF840 ER3=00000000 ER4=00000000 ER5=00000000 ER6=00000000 ER7=000FFF00 : d ff800 ff84f <ADDR> < D A T A > < ASCII CODE > FF800 00 00 01 00 00 00 28 16 00 00 28 1A 00 00 28 1E "......(...(...(." FF810 00 00 28 22 00 00 28 26 00 00 28 2A 00 00 28 2E "..("..(&..(*..(." FF820 00 00 28 32 00 00 28 36 00 00 28 3A 00 00 28 3E "..(2..(6..(:..(>" FF830 00 00 28 42 00 00 28 46 00 00 28 4A 00 00 28 4E "..(B..(F..(J..(N" FF840 AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA "................" : |
課題5.1 |
テキストエディタとアセンブラを用いて次のプログラムを作成しなさい。 プログラム本体および以下を報告しなさい。 プログラムの逆アッセンブル結果 補足
次のように記述するとコピー元とコピー先が指定の場所に確保できる
.SECTION D,DATA,LOCATE=H'0FF800 |
6. IOポート
(1)LEDの点灯
ここでアセンブリプログラムによるIOポートへのアクセスを試みる。
IOポートのうち,LEDのつながれているP5と,8bitスイッチがつながれているP2を対象とする。
LED0,LED1はP5(正確にはP5DR)のbit0,bit1に保護抵抗を介して接続されている。P5と呼んでいるポートの実体はメモリ空間に割り当てられているIOレジスタである。
LEDの点滅をするためには,次の2つのことが必要である。点滅対象はLED0の1つだけとする。
(1)P5DDR(Data Direction Register)は,P5DRの各ビットを入力(外部から0Vor5VをCPUとし
て0or1として受け取る)か出力(CPUの0or1を外部に対して0Vor5Vとして出力する)かを決
定するレジスタである。
各ビットを1にすると出力設定となり,0にすると入力設定となる。
ここではbit0を1にするとLED0への出力となる。
(2)P5DRは,CPUが書き込んだ値をそのままCPUのピンにそのまま出力する8ビットのレジスタである。
このレジスタのbit0に1を出力すると5Vが出力され点灯,0を出力すると0Vが出力され消灯する。H8/3048のハードウェアマニュアルによれば,P5DDRはメモリ空間上の1byteのように見える。
P5DDRのアドレスは,0xFFFC8である。
同様にP5DRもメモリ空間上の1byteのように見える。
P5DRのアドレスは。0xFFFCAである。
これらのアドレスは,CPU設計時に決められているため,変更することはできない。モニタプログラムのmコマンド(メモリ直接書き込み)で,LEDの点滅をさせてみよう。
fffc8に3を設定してP5の下位2ビットを出力に設定
その後,fffcaに01,02,03,00の順に値をするとLED0のみ点灯,LED1のみ点灯,両方点灯,両方消灯の順に推移する。
次のようにモニタプログラムでLED点灯を確認しなさい。
: m fffc8
FFFC8 FF ? 03
FFFC9 FF ? .
: m fffca
FFFCA F0 ? 01
FFFCB FB ? .
: m fffca
FFFCA F1 ? 02
FFFCB FB ? .
: m fffca
FFFCA F2 ? 03
FFFCB FB ? .
: m fffca
FFFCA F3 ? 00
FFFCB FB ? .
:
P5の下位2ビットを出力に設定
LED0のみ点灯
LED1のみ点灯
両LED点灯
消灯注意
FFFC8はwrite onlyレジスタなので,読み出してもレジスタの内容を
読み出すことができない。したがって,モニタプログラムでFFFC8を
表示させても,表示されている値はレジスタの値とは異なる(ごみ値)FFCAは下位4ビットのみ有効である。上位4ビットに値を書き込むこと
はできない。このレジスタの内容を読み出しても,上位4ビットは読
み出すことができず,モニタプログラムで表示しても上位4ビットは
不定値である。(ここでは上位4ビットに1が見えている)次のプログラムは,P5DDRのbit0を出力に設定したのち,P5DRのbit0に向けて1と0を交互に出力する。
LED点滅プログラム
.CPU 300HA
P5DDR .EQU H'FFFC8
P5DR .EQU H'FFFCA.SECTION A,DATA,LOCATE=H'0FF030
.DATA.L H'0FF130 ;リセットベクトル.SECTION P,CODE,LOCATE=H'0FF130
MOV.L #H'FFF00,ER7 ;スタックポインタ設定
MOV.B #H'1, R1L ; 00000001(2進数表現) を 8bitレジスタR1Lへ
MOV.B R1L, @P5DDR ; 8bitレジスタR1Lにある値をアドレスP5DDRへ
EternalLoop:
MOV.B #H'1, R0L ; 00000001(2進数表現) を 8bitレジスタR0Lへ
MOV.B R0L, @P5DR ; 8bitレジスタR0Lにある値をアドレスP5DRへ
MOV.B #H'0, R0L ; 00000000(2進数表現) を 8bitレジスタR0Lへ
MOV.B R0L, @P5DR ; 8bitレジスタR0Lにある値をアドレスP5DRへ
BRA EternalLoop ;永久ループ.END
このプログラムを実行形式にして,モニタプログラム上に読み込み,ステップ実行を続けると
LEDの点滅が見られる。
なお,.EQUというのは,C言語の#defineの働きをしている。プログラム本体に「P5DDR」
が出てきたら,それは「H'FFFC8」としてアセンブルしなさいの意味である。
課題3 |
上記のプログラムを動かして,LED0の点滅を確かめなさい。 (mon2ex03.txt) |
(2)スイッチの状態取得
次に,LEDの点滅を8ビットDIPスイッチで制御してみよう。
8ビットスイッチは,ポート2(P2)に接続されている。内部にはプルアップコントロールといって,プルアップ抵抗を介して電源につなげることを有効にする機能がある。
P2と呼んでいるポートの実体はメモリ空間に割り当てられているIOレジスタである。
8ビットスイッチの状態を取得するには,次の3つのことが必要である。取得対象はDIPSW0の1つだけとする。
(1)P2DDR(Data Direction Register)と呼ばれる入出力方向を設定するレジスタのbit0に,
出力として使うという設定を行なう。このビットを0にすると入力設定となる。
(このビットを1にすると出力設定となる)
(2)P2PCR(Pullup Control Register)と呼ばれるプルアップ制御を設定するレジスタのbit0に,
プルアップ有効という設定を行なう。このビットを1にするとプルアップ有効設定となる。
(このビットを0にするとプルアップ無効設定となる)
(3)P2DRは,CPUのピンの状態をそのまま汎用レジスタに入力するする8ビットのレジスタである。
このレジスタのbit0に5Vを与えると1が,0Vを与えると0が入力される。H8/3048のハードウェアマニュアルによれば,P2DDRはメモリ空間上の1byteのように見える。
P2DDRのアドレスは,0xFFFC1である。
同様にP2PCRもメモリ空間上の1byteのように見える。
P2PCRのアドレスは。0xFFFD8である。
同様にP2DRもメモリ空間上の1byteのように見える。
P2DRのアドレスは。0xFFFC3である。
これらのアドレスは,CPU設計時に決められているため,変更することはできない。
課題4 |
モニタプログラムのコマンドで,8ビットDIPスイッチのビット
パタンを読み取れていることを確かめてみよう。 レポートでは,8ビットDIPスイッチの状態とfffc3の内容 の対応を5例ほど示しなさい。 (mon2ex04.txt) |
(3)スイッチの状態取得とLED点滅
次のプログラムは,8ビットスイッチのSW0のON-OFFの状態を取り込み,それに対応して,
LED0を点灯あるいは消灯させる。
8ビットスイッチの状態取得とLED制御プログラム
.CPU 300HA
P5DDR .EQU H'FFFC8
P5DR .EQU H'FFFCA
P2DDR .EQU H'FFFC1
P2DR .EQU H'FFFC3
P2PCR .EQU H'FFFD8.SECTION A,DATA,LOCATE=H'0FF030
.DATA.L H'0FF130 ;リセットベクトル.SECTION P,CODE,LOCATE=H'0FF130
MOV.L #H'FFF00,ER7 ;スタックポインタ設定
MOV.B #H'1, R1L ; 00000001(2進数表現) を 8bitレジスタR1Lへ
MOV.B R1L, @P5DDR ; 8bitレジスタR1Lにある値をアドレスP5DDRへ
MOV.B #H'0, R1L ; 00000000(2進数表現) を 8bitレジスタR1Lへ
MOV.B R1L, @P2DDR ; 8bitレジスタR1Lにある値をアドレスP2DDRへ
MOV.B #H'1, R1L ; 00000001(2進数表現) を 8bitレジスタR1Lへ
MOV.B R1L, @P2PCR ; 8bitレジスタR1Lにある値をアドレスP2PCRへ
EternalLoop:
MOV.B @P2DR, R0L ; アドレスP2DR を 8bitレジスタR0Lへ
MOV.B R0L, @P5DR ; 8bitレジスタR0Lにある値をアドレスP5DRへ
BRA EternalLoop ;永久ループ.END
このプログラムを実行形式にして,モニタプログラム上に読み込み,ステップ実行を続けると
8ビットスイッチのSW0のON-OFF状態に対応したLEDの点滅が見られる。
課題5 |
上記のプログラムを動かして,8ビットスイッチのSW0の変更と
LED0の点滅を確かめなさい。 (mon2ex05.txt) |
7. 乗算・除算
2進数の掛け算はつぎのようなイメージである。
10110 最初のr0 .
例 10110×1010=1101110
10110 .
× 1010 .
10110 .
10110 .
11011100 .
桁を省略せずに書くと次のようになる。
× 1010 . 最初のr1 s
101100 . 左シフト中のr0
10110000 . 左シフト中のr0
11011100 . r2(最初は0,シフト中のr0を加算している)
アセンブリプログラムでの乗算は,シフト命令と加算命令で作ることができそうである。
この考え方をC言語で書いてみると次のようになる。
mult_PC.c
掛け算をシフトと足し算で行うCプログラム。これはPCで実行できる。
#include "stdio.h"
int main()
{
int x00,x10;
int x0,x1,x2; //x2=x0*r1を作る
scanf("%d %d",&x00,&x10);
x0=x00;
x1=x10;
x2=0;
do {
if(x1&1) x2+=x0;
x0<<=1;
x1>>=1;
} while (x1);
printf("x00,x10,x2= %04x, %04x, %04x\n",x00,x10,x2);
printf("x00,x10,x2=%6d,%6d,%6d\n",x00,x10,x2);
}
/*実行例
85 10
x00,x10,x2= 0055, 000a, 0352
x00,x10,x2= 85, 10, 850
*/
mult.c
掛け算Cプログラム(mult_PC.c)を次のように改めて,c2asm.cmd
でアセンブリプログラムに変換すると,カンニングができる。
グローバル変数はメモリに明示的に割り当てられ,オート変数は
レジスタに割り当てられる。
short int x00=0x55;
short int x10=0xa;
short int y0; /* x0=x00*x10 */
int main()
{
short int x0,x1,x2;
x0=x00;
x1=x10;
x2=0;
do {
if(x1&1) x2+=x0;
x0<<=1;
x1>>=1;
} while (x1);
y0=x2;
}
一方2進数の割り算は次のようなイメージである。
例 10110110÷1010=10010 余り 10
10010 .
1010 )10110110 .
1010 .
1011 .
1010 .
10
桁を省略せずに書くと次のようになる。
最初はr0に10110110を,r1に1010を入れておく
10010 . r2に答えが作られる (r2の初期値は0)
1010 )10110110 . r0(最初の状態)
10100000 . r0を超えないように,r1を左シフトした
10110 . r0(r1を引いたところ)
10100 . r1を右シフト
10 あまりはr0に残る
アセンブリプログラムでの除算は,シフト命令とシフト命令と減算命令(CMP命令を用いると引くことができるかどうかわかる)で作ることができそうである。
割り算をシフトと引き算で行うCプログラム
#include "stdio.h"
int main()
{
int x00,x10;
int x0,x1,x2; //x0÷x1=x2 あまり x0を作る
int x3;
scanf("%d %d",&x00,&x10);
x0=x00;
x1=x10;
x2=0;
x3=1;
while (x1<x0) {
x1<<=1;
x3<<=1;
}
while (x3!=0) {
if(x1<=x0) {
x0-=x1;
x2+=x3;
}
x1>>=1;
x3>>=1;
}
printf("x00,x10,x2,x0= %04x, %04x, %04x, %04x\n",x00,x10,x2,x0);
printf("x00,x10,x2,x0=%6d,%6d,%6d,%6d\n",x00,x10,x2,x0);
}
/*実行例
135 10
x00,x10,x2,x0= 0087, 000a, 000d, 0005
x00,x10,x2,x0= 135, 10, 13, 5
1025 25
x00,x10,x2,x0= 0401, 0019, 0029, 0000
x00,x10,x2,x0= 1025, 25, 41, 0
*/
割り算Cプログラムを次のように改めて,前に使ったc2asm.cmd
でアセンブリプログラムに変換すると,カンニングができる。
グローバル変数はメモリに明示的に割り当てられ,オート変数は
レジスタに割り当てられる。
short int x00=0x87;
short int x10=0xa;
short int y0,y1; /* x00 div x10 = y1 ... y0 */
int main()
{
short int x0,x1,x2,x3;
x0=x00;
x1=x10;
x2=0;
x3=1;
while (x1<x0) {
x1<<=1;
x3<<=1;
}
while (x3!=0) {
if(x1<=x0) {
x0-=x1;
x2+=x3;
}
x1>>=1;
x3>>=1;
}
y1=x2;
y0=x0;
}
参考 アセンブリ言語によるいくつかの条件ジャンプの例
CMP.W #12345:16,R0
BLT ABCD:8R0 less than #12345:16 なら
ラベルABCD:へジャンプCMP.W R5,R0
BGT LOOP2:8R0 grater than R5 なら
ラベルLOOP2へジャンプMOV.W E0,E0
BNE ZERO:8E0 Not Equal 0 なら
ラベルZEROへジャンプ
Cプログラムをアセンブリプログラムに変換するツール
((本校)LANからのみ試用のためアクセスできる。)
(4J電子計算機IIの授業ではこれを使う)
c2asm.cmdにxxx.cをドロップすると,xxx.srcとxxx_1.srcが作成されるが,
xxx_1.srcはxxx.srcからコメント行を消去したものである。
課題6 |
1.テキストエディタとアセンブラを用いて次のプログラムを作成しな
さい。 ヒント プログラムの骨組み 2.テキストエディタと
アセンブラを用いて次のプログラムを作成しなさい。
|
課題7 |
1.テキストエディタとアセンブラを用いて次のプログラムを作成しなさい。 関数は戻り値をr0に載せて返すことになっている。 c2asm.html(Cプログラムをアセンブリプログラムに変換)の 「【6】関数呼び出し(2引数)と関数の戻り値」を参照しなさい ヒント2
プログラムの骨組み 2.テキストエディタと
アセンブラを用いて次のプログラムを作成しなさい。 |
8.参考(1) アッセンブルコマンド「Asm2Mon.cmd」
Asm2Mon.cmd |
rem
------------------------------------------------------------------------ @echo off rem カレントドライブ・カレントディレクトリへ移動 rem コンパイラのパスの設定 rem
誤ったファイルがドロップされたか,単なるダブルクリックで起動した場合は何もしない :ASSEMBLE :LINK :CONVERT goto TERMINAL :NO_SOURCE_ERROR :ASM_ERROR :LINK_ERROR :TERMINAL |
9.参考(2)h8v2フォルダの構成例
h8v2の構成例 |
C:\Program Files\h8v2 ├─BIN │ ASM38.EXE │ C38ASM.EXE │ C38CGN.EXE │ C38FRNT.EXE │ C38MID.EXE │ C38PEP.EXE │ CH38.EXE │ CNVS.EXE │ h8v2cc.cmd │ LNK.EXE │ OPT38.EXE │ OPTLNK38.EXE │ ├─INCLUDE │ 3048F.H │ 3048FONE.H │ 3048S.H │ 3664S.H │ ASSERT.H │ CTYPE.H │ ERRNO.H │ FLOAT.H │ INDIRECT.H │ LIMITS.H │ MACHINE.H │ MATH.H │ NO_FLOAT.H │ SETJMP.H │ STDARG.H │ STDDEF.H │ STDIO.H │ STDLIB.H │ STRING.H │ ├─LIB │ │ C38HA.LIB │ │ C38HAS.LIB │ │ C38HN.LIB │ │ C38HNS.LIB │ │ C38REG.LIB │ │ C38REGS.LIB │ │ C8S26A.LIB │ │ C8S26AS.LIB │ │ C8S26N.LIB │ │ C8S26NS.LIB │ │ start3048.OBJ │ │ start3048I.OBJ │ │ │ |