AKI-H8/3048foneのモニタプログラムでの
機械語プログラムの動作

Copyright(C)12Mar2014
since 1Aug2003
coskx


1.はじめに

この文書は,AKI-H8におけるH8/3048foneのモニタプログラム,PCターミナルソフトでの学習を記述している。
モ ニタプログラムは,新しいプログラムの動作を検証する場合や,アセンブリ言語の学習者が,1命令ずつ機械語命令を実行してCPUのふるまいを観察するプロ グラムである。モニタプログラムはROM(フラッシュメモリ)上に配置されており,検証対象のプログラムはRAM上に置かれる。

この文書では
PC上のターミナル画面からアセンブリニーモニックを直接入力してCPUの動作を見る方法
を用いて,機械語プログラムの動作を解説する。

(本校)校内からは授業に使うため準備用ファイルが入手できる。またマニュアルもダウンロードしておくとよい。

このファイルを解凍すると「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)

または

E0 (16bit)

R0H (8bit)

R0L (8bit)

                  レジスタER0の構造と使われ方

ER0の構造はER1,ER2,ER3,ER4,ER5,ER6でも同じである。
例えばER1では次のようになっている

ER1 (32bit)

または

E1 (16bit)

R1 (16bit)

または

E1 (16bit)

R1H (8bit)

R1L (8bit)

                  レジスタER1の構造と使われ方

もう一例を上げれば,ER2では次のようになっている

ER2 (32bit)

または

E2 (16bit)

R2 (16bit)

または

E2 (16bit)

R2H (8bit)

R2L (8bit)

                  レジスタER2の構造と使われ方

bit,byteと16進表示についてまとめておこう


ビット数
バイト数
16進表現桁数
表現範囲
略号
バイト
8bit
1byte
2桁
00-FF
B
ワード
16bit
2byte
4桁
0000-FFFF
W
ロングワード
32bit
4byte
8桁
00000000-FFFFFFFF
L




2. 2つの2バイト整数値の演算

2つの2バイト整数値の演算を行う。
メモリ保存値同士の演算は出来ないので,メモリ保存値をレジスタに移動してから演算し,演算結果をメモリに移動する。

目的 モニタプログラム上で,簡単なアセンブリプログラムを記述し,ステップ実行し,モニタプログラムの操作を修得するする。
また,各レジスタが変化する様子,メモリ上の変数の取扱いを確認する。
例題1

FF200から機械語プログラムを置きなさい。
FF800番地の2byteデータをレジスタR0に載せる(実際にはFF800,FF801番地)
FF802番地の2byteデータをレジスタR1に載せる(実際にはFF802,FF803番地)
R0からR1の値を引いてR0にしまう
R0のデータをFF804番地にしまう(実際にはFF804,FF805番地)
終端処理(無限ループにしておく)

実行時に,FF800,FF801番地の2byteデータには3456を
FF802,FF803番地の2byteデータには7890をセットして以下を報告しなさい。
実行前のFF800番地?FF80F番地の様子
プログラムの逆アッセンブル結果
1命令ごとに実行して実行の様子
実行後のFF800番地?FF80F番地の様子

実行例 : a ff200
  FF200   >  mov.l #fff00,er7
  FF206   >  mov.w @ff800:24,r0
  FF20C   >  mov.w @ff802:24,r1
  FF212   >  sub.w r1,r0
  FF214   >  mov.w r0,@ff804:24
  FF21A   >  bra ff21a:8
  FF21C   >  .
: da ff200 ff21a
  <ADDR>  <CODE>                <MNEMONIC> <OPERAND>
  FF200   7A07000FFF00          MOV.L      #H'000FFF00:32,ER7
  FF206   6B20000FF800          MOV.W      @H'FF800:24,R0
  FF20C   6B21000FF802          MOV.W      @H'FF802:24,R1
  FF212   1910                  SUB.W      R1,R0
  FF214   6BA0000FF804          MOV.W      R0,@H'FF804:24
  FF21A   40FE                  BRA        FF21A:8
: d ff800 ff80f
  <ADDR>                  <  D  A  T  A  >                     < ASCII CODE >
  FF800   00 00 FF EE 00 00 FF FF  00 A0 FF FF 00 00 FF FF   "................"
: m ff800
  FF800   00  ?  34
  FF801   00  ?  56
  FF802   FF  ?  78
  FF803   EE  ?  90
  FF804   00  ?  00
  FF805   00  ?  00
  FF806   FF  ?  .
: d ff800 ff80f
  <ADDR>                  <  D  A  T  A  >                     < ASCII CODE >
  FF800   34 56 78 90 00 00 FF FF  00 A0 FF FF 00 00 FF FF   "................"
: r
  PC=000000  CCR=80:I.......  SP=00FFFF10
  ER0=00000000  ER1=00000000  ER2=00000000  ER3=00000000
  ER4=00000000  ER5=00000000  ER6=00000000  ER7=00FFFF10
: .pc
  PC=000000  ?  ff200
  CCR=80  ?  .
: r
  PC=0FF200  CCR=80:I.......  SP=00FFFF10
  ER0=00000000  ER1=00000000  ER2=00000000  ER3=00000000
  ER4=00000000  ER5=00000000  ER6=00000000  ER7=00FFFF10
: s
  PC=0FF206  CCR=80:I.......  SP=000FFF00
  ER0=00000000  ER1=00000000  ER2=00000000  ER3=00000000
  ER4=00000000  ER5=00000000  ER6=00000000  ER7=000FFF00
  FF200   7A07000FFF00          MOV.L      #H'000FFF00:32,ER7
: s
  PC=0FF20C  CCR=80:I.......  SP=000FFF00
  ER0=00003456  ER1=00000000  ER2=00000000  ER3=00000000
  ER4=00000000  ER5=00000000  ER6=00000000  ER7=000FFF00
  FF206   6B20000FF800          MOV.W      @H'FF800:24,R0
: s
  PC=0FF212  CCR=80:I.......  SP=000FFF00
  ER0=00003456  ER1=00007890  ER2=00000000  ER3=00000000
  ER4=00000000  ER5=00000000  ER6=00000000  ER7=000FFF00
  FF20C   6B21000FF802          MOV.W      @H'FF802:24,R1
: s
  PC=0FF214  CCR=A9:I.H.N..C  SP=000FFF00
  ER0=0000BBC6  ER1=00007890  ER2=00000000  ER3=00000000
  ER4=00000000  ER5=00000000  ER6=00000000  ER7=000FFF00
  FF212   1910                  SUB.W      R1,R0
: s
  PC=0FF21A  CCR=A9:I.H.N..C  SP=000FFF00
  ER0=0000BBC6  ER1=00007890  ER2=00000000  ER3=00000000
  ER4=00000000  ER5=00000000  ER6=00000000  ER7=000FFF00
  FF214   6BA0000FF804          MOV.W      R0,@H'FF804:24
: d ff800 ff80f
  <ADDR>                  <  D  A  T  A  >                     < ASCII CODE >
  FF800   34 56 78 90 BB C6 FF FF  00 A0 FF FF 00 00 FF FF   "4Vx............."
:
アセンブリ言語プログラム
の入力






逆アッセンブルで確認







作業用メモリの確認


作業用メモリにテストデータ
を載せる






作業用メモリのテストデータ
が変化したことの確認

レジスタの確認



プログラムカウンタのセット


レジスタの確認
(プログラムカウンタに注目)


1命令実行
























実行結果メモリの確認
3456(Hex)-7890(Hex)
=BBC6(Hex)が検証できる

 
・ MOV命令に関する補足

MOV命令の意味は,move(移動)だが,コンピュータの性格上,転送元のデータが消えてしまうことは無く,コピーされるだけである。

MOV(move)命令は,「MOV.W @H'FF800:24,R0」のように使われるが,
「MOV.転送データサイズ 転送元,転送先」
の順で記述されている。

・転送データサイズは,B,W,Lの3つのうちのどれかで,B:バイト(8bit),W:ワード(16bit),L:ロングワード(32bit)を表している。
・転送元はメモリ上のある番地,値(即値)あるいはレジスタ名のいずれかを書く。
  値(即値)の場合は先頭に「#」を,メモリ上の番地の場合は先頭に「@」を書き,
  da命令のときは,16進法表現の場合は「H'」が付けられる。
  また番地の場合はその番地を表すビット数を後ろにつける。
  H'FF800:24の24が番地を表すのに使っているビット数である。
・転送先にはメモリ上のある番地,あるいはレジスタ名のいずれかを書く。
 ただし,メモリ中のある番地に保存されている値を直接他の番地に移すことはできない。
 
メモリ中のある番地に保存されている値を直接他の番地に移したいときには,
 一度,メモリ中の値をレジスタに移し,そのレジスタの値を別のアドレスのメモリに移せばよい。


MOV.L
@H'FF800:24,ER0      FF800番地から始まる4バイトをER0に移せ
MOV.W @H'FF800:24,R0       FF800番地から始まる2バイトをR0に移せ
MOV.B @H'FF800:24,R0L      FF800番地から始まる1バイトをR0Lに移せ

MOV.L
#H'1234CDEF,ER0      4バイトの値1234CDEF(16進法表示)をER0に移せ
MOV.W #H'12EF,R0           2バイトの値12EF(16進法表示)をR0に移せ
MOV.B #H'1F,R0L            1バイトの値1F(16進法表示)をR0Lに移せ

なお MOV.L @H'FF800:24,R0 は転送サイズと宛先レジスタサイズが一致しないため,実行できない。

また, MOV.W @H
'FF800:24,@H'FF802:24 はメモリ間の転送命令になってしまうので,不当命令である


・ PCは,1つの機械語命令の実行で,どのように変化するか(補足説明

 CPUは演算のためのER0,ER1などのレジスタ,PC(プログラムカウンタ),表示には現れないが,読み出した機械語命令,今のところ使 用していないSP(スタックポインタ),CCR(コンディションコードレジスタ)しか持っていない。上記の作業では最初にプログラムリストを表示させてい るが,それはモニタプログラムが表示しているだけで,プログラムリストをCPUが持っているわけではない。
 メモリ上のあるアドレスに格納されて いる機械語命令を実行した直後にPCの値が変化しているが,次に行うべき機械語命令のアドレスを,プログラムリストを見て決めているのではない。人間はプ ログラムリストを見て,次の機械語命令の格納されているアドレスを知ることができるのとはまったく異なる。
CPUは現在実行すべき機械語命令の最初の1バイトを見て,その機械語命令が何バイト構成かわかり,そのバイト数だけ,メモリから順番に命令を読み出す。読み終わった次のアドレスをPCに格納している。そしてその機械語命令を実行する。
この単純な作業を行っているだけだが,プログラムリストを上から1行ずつ実行しているように人間には見えている。

H8命令ニーモニクの説明マニュアル 学内高速読み取りバッファより


課題1 変数アドレスを変更したバージョンの引き算

FF200から機械語プログラムを置きなさい。
FF700,FF701番地の2byteデータをレジスタR0に載せる
FF702,FF703番地の2byteデータをレジスタR1に載せる
R0からR1の値を引いてR0にしまう
R0のデータをFF704,FF705番地にしまう

作成したプログラム本体を報告に載せなさい。

実行時に,FF700,FF701番地の2byteデータにはab78を
FF702,FF703番地の2byteデータには7643をセットして全作業を報告しなさい。

ただし,以下の内容を含むこと
実行前のFF700番地?FF70F番地の様子
プログラムの逆アッセンブル結果
1命令ごとに実行して実行の様子
実行後のFF700番地?FF70F番地の様子

また,sコマンドで1ステップ進めるごとに,PC(プログラムカウンタ)
の値が変化するが,変化量は何に依存しているのかを考察に含めなさい。
(mon1ex01.txt)

 

3. 複数の2バイト整数データの演算

目的 モニタプログラム上で,簡単なアセンブリプログラムを記述し,ステップ実行し,
各レジスタが変化する様子を確認する。
例題2

FF200から機械語プログラムを置きなさい。
FF800,FF801番地の2byteデータ(2byteデータ=ワードデータ),
FF802,FF803番地の2byteデータ,
FF804,FF805番地の2byteデータ,
FF806,FF807番地の2byteデータをすべて加え,
FF808,FF809番地の2byteデータにしなさい。
オーバーフローしてもかまわないこととする。

実行時に4つのデータを適当にセットし,以下を実行する。
実行前のFF800番地?FF810番地の様子を見る
プログラムの逆アッセンブル結果
1命令ごとに実行して実行の様子
実行後のFF800番地?FF810番地の様子を見る

実行例 : a ff200
  FF200   >  mov.w @ff800:24,r0
  FF206   >  mov.w @ff802:24,r1
  FF20C   >  add.w r1,r0
  FF20E   >  mov.w @ff804:24,r1
  FF214   >  add.w r1,r0
  FF216   >  mov.w @ff806:24,r1
  FF21C   >  add.w r1,r0
  FF21E   >  mov.w r0,@ff808:24
  FF224   >  .
: m ff800
  FF800   34  ?  00
  FF801   56  ?  01
  FF802   78  ?  00
  FF803   90  ?  12
  FF804   BB  ?  00
  FF805   C6  ?  22
  FF806   FF  ?  00
  FF807   FF  ?  31
  FF808   00  ?  .
: d ff800 ff80f
  <ADDR>                  <  D  A  T  A  >                     < ASCII CODE >
  FF800   00 01 00 12 00 22 00 31  00 00 FF FF 00 00 FF FF   ".....".1........"
: da ff200 ff21e
  <ADDR>  <CODE>                <MNEMONIC> <OPERAND>
  FF200   6B20000FF800          MOV.W      @H'FF800:24,R0
  FF206   6B21000FF802          MOV.W      @H'FF802:24,R1
  FF20C   0910                  ADD.W      R1,R0
  FF20E   6B21000FF804          MOV.W      @H'FF804:24,R1
  FF214   0910                  ADD.W      R1,R0
  FF216   6B21000FF806          MOV.W      @H'FF806:24,R1
  FF21C   0910                  ADD.W      R1,R0
  FF21E   6BA0000FF808          MOV.W      R0,@H'FF808:24
: r
  PC=0FF21A  CCR=A9:I.H.N..C  SP=000FFF00
  ER0=0000BBC6  ER1=00007890  ER2=00000000  ER3=00000000
  ER4=00000000  ER5=00000000  ER6=00000000  ER7=000FFF00
: .pc
  PC=0FF21A  ?  ff200
  CCR=A9  ?  .
: s
  PC=0FF206  CCR=A1:I.H....C  SP=000FFF00
  ER0=00000001  ER1=00007890  ER2=00000000  ER3=00000000
  ER4=00000000  ER5=00000000  ER6=00000000  ER7=000FFF00
  FF200   6B20000FF800          MOV.W      @H'FF800:24,R0
: s
  PC=0FF20C  CCR=A1:I.H....C  SP=000FFF00
  ER0=00000001  ER1=00000012  ER2=00000000  ER3=00000000
  ER4=00000000  ER5=00000000  ER6=00000000  ER7=000FFF00
  FF206   6B21000FF802          MOV.W      @H'FF802:24,R1
: s
  PC=0FF20E  CCR=80:I.......  SP=000FFF00
  ER0=00000013  ER1=00000012  ER2=00000000  ER3=00000000
  ER4=00000000  ER5=00000000  ER6=00000000  ER7=000FFF00
  FF20C   0910                  ADD.W      R1,R0
: s
  PC=0FF214  CCR=80:I.......  SP=000FFF00
  ER0=00000013  ER1=00000022  ER2=00000000  ER3=00000000
  ER4=00000000  ER5=00000000  ER6=00000000  ER7=000FFF00
  FF20E   6B21000FF804          MOV.W      @H'FF804:24,R1
: s
  PC=0FF216  CCR=80:I.......  SP=000FFF00
  ER0=00000035  ER1=00000022  ER2=00000000  ER3=00000000
  ER4=00000000  ER5=00000000  ER6=00000000  ER7=000FFF00
  FF214   0910                  ADD.W      R1,R0
: s
  PC=0FF21C  CCR=80:I.......  SP=000FFF00
  ER0=00000035  ER1=00000031  ER2=00000000  ER3=00000000
  ER4=00000000  ER5=00000000  ER6=00000000  ER7=000FFF00
  FF216   6B21000FF806          MOV.W      @H'FF806:24,R1
: s
  PC=0FF21E  CCR=80:I.......  SP=000FFF00
  ER0=00000066  ER1=00000031  ER2=00000000  ER3=00000000
  ER4=00000000  ER5=00000000  ER6=00000000  ER7=000FFF00
  FF21C   0910                  ADD.W      R1,R0
: s
  PC=0FF224  CCR=80:I.......  SP=000FFF00
  ER0=00000066  ER1=00000031  ER2=00000000  ER3=00000000
  ER4=00000000  ER5=00000000  ER6=00000000  ER7=000FFF00
  FF21E   6BA0000FF808          MOV.W      R0,@H'FF808:24
: d ff800 ff80f
  <ADDR>                  <  D  A  T  A  >                     < ASCII CODE >
  FF800   00 01 00 12 00 22 00 31  00 66 FF FF 00 00 FF FF   ".....".1.f......"
:
実行後
和が作られたはずだが,どこに作られたのか,正しく計算結果が得られているのか確かめなさい。

H8命令ニーモニクの説明マニュアル 学内高速読み取りバッファより


課題2 4つのデータの和を作る

FF200から機械語プログラムを置きなさい。
FF700,FF701番地の2byteデータ,FF702,FF703番地の2byteデータ,FF704,FF705番地の2byteデータ,
FF706,FF707番地の2byteデータをすべて加え,FF708,FF709番地の2byteデータにしなさい。
オーバーフローしてもかまわないこととする。

作成したプログラム本体を報告に載せなさい。

実行時に4つのデータを適当にセットし,全作業を報告しなさい。
ただし,以下の内容を含むこと
実行前のFF700番地?FF710番地の様子
プログラムの逆アッセンブル結果
1命令ごとに実行して実行の様子
実行後のFF700番地?FF710番地の様子

1つの機械語命令を実行すると,プログラムカウンタの値が増加するが,増分値は
何に依存するのかを考察に盛り込みなさい。
4つの値の和は幾つになるのが正解で,それはどこに見えているのかも盛り込みなさい。
(mon1ex02.txt)

 

4. ジャンプ命令

ジャンプ命令はPC(プログラムカウンタ)を書き換えることで,実現されていることを確認しよう。

目的 ジャンプ命令を実行するとプログラムカウンタが書き換えられて,ジャンプ先の命令を実行するようになることを確認する。
例題3

FF200から機械語プログラムを置きなさい。
ジャンプ命令を1つだけを書きなさい。
ジャンプ先アドレスは適当でかまわない。
1命令実行後のプログラムカウンタがどうなったか調べなさい。
3例ほど行い,結果を報告しなさい。
jmp命令では jmp @ff230:24
bra命令では bra ff230:8
のように書く

jmp命令は絶対アドレス(24ビット)指定(4バイト命令)のジャンプ命令
bra命令は相対アドレス(8ビット±127以下)指定(2バイト命令)のジャンプ命令(branch分岐の意味)
ただしbra命令は:8でなく:16と書くと,相対アドレス(16ビット±32767以下)指定(4バイト命令)
のジャンプ命令となる。

bra ff230:8  相対アドレス(8ビット±127以下)指定のジャンプ命令
bra ff230:16 相対アドレス(16ビット±32767以下)指定のジャンプ命令

実行例1

jmp命令

PCの変化に
注目
: a ff200
  FF200   >  jmp @ff300:24
  FF204   >  .
: da ff200 ff200
  <ADDR>  <CODE>                <MNEMONIC> <OPERAND>
  FF200   5A0FF300              JMP        @H'FF300:24
: .pc
  PC=0FF224  ?  ff200
  CCR=80  ?  .
: r
  PC=0FF200  CCR=80:I.......  SP=000FFF00
  ER0=00000066  ER1=00000031  ER2=00000000  ER3=00000000
  ER4=00000000  ER5=00000000  ER6=00000000  ER7=000FFF00
: s
  PC=0FF300  CCR=80:I.......  SP=000FFF00
  ER0=00000066  ER1=00000031  ER2=00000000  ER3=00000000
  ER4=00000000  ER5=00000000  ER6=00000000  ER7=000FFF00
  FF200   5A0FF300              JMP        @H'FF300:24
:














本来なら4バイト命令だから,PCはFF204になるはずであったが,ジャンプ命令(=PC書き換え命令)のためPCはFF300になってしまった。

実行例2

bra命令

PCの変化に
注目
: a ff200
  FF200   >  bra ff210:8
  FF202   >  .
: da ff200 ff200
  <ADDR>  <CODE>                <MNEMONIC> <OPERAND>
  FF200   400E                  BRA        FF210:8
: .pc
  PC=0FF22E  ?  ff200
  CCR=80  ?  .
: r
  PC=0FF200  CCR=80:I.......  SP=000FFF00
  ER0=12344321  ER1=34566543  ER2=00000000  ER3=00000000
  ER4=00000000  ER5=00000000  ER6=00000000  ER7=000FFF00
: s
  PC=0FF210  CCR=80:I.......  SP=000FFF00
  ER0=12344321  ER1=34566543  ER2=00000000  ER3=00000000
  ER4=00000000  ER5=00000000  ER6=00000000  ER7=000FFF00
  FF200   400E                  BRA        FF210:8














本来なら2バイト命令だから,PCはFF202になるはずであったが,ジャンプ命令(=PC書き換え命令)のためPCはFF210になってしまった。

解説

 人間は,プログラムリストを見て,「ここにジャンプ命令があるから,次はこちらにプログラム実行の流れが変わって・・・」といように理解するが,CPUはプログラムリスト全体を見てジャンプするわけではない。
ジャ ンプ命令内に,ジャンプすべきアドレスに関する情報が埋め込まれており,その情報をもとに,ジャンプすべきアドレスをPC(プログラムカウンタ)に書き込 んでいるだけである。その結果,次に行うべき機械語命令が離れた場所から読みだされる結果となってしまい,人間から見ると,作業の流れがジャンプしたように見える。(PCが書き換わってしまったためにCPUがだまされる)

ジャンプ命令はPC(プログラムカウンタ)書き換え命令である。

H8命令ニーモニクの説明マニュアル 学内高速読み取りバッファより

補足説明 絶対アドレスジャンプ命令(JMP)と相対アドレスジャンプ命令(BRA)

絶対アドレスジャンプ命令は,機械語命令中にジャンプ先アドレスが書かれている。上の例では,
「jmp @ff300:24」は3バイト命令「5A0FF300」に翻訳されている。「5A」が「JMP」にあたり,「0FF300」のアドレスが
そのまま書かれている。

相対アドレスジャンプ命令は,ジャンプ命令のすぐ次の命令の置かれているアドレス値にからどれくらい離れたところにジャンプするかを示すようになっている。
上の例では,「bra ff210:8」は2バイト命令「400E」に翻訳されている。40がブランチ(ジャンプ)命令で,0Eがアドレス増加量である。
FF200におかれた機械語「400E」は2バイトなので,本来ならPCはFF202になるはずである。
FF202+0E=FF210なのでこの命令の直後にPCはFF210になる。
相対アドレスジャンプ命令で書かれたプログラムは,プログラムモジュールが別のアドレスに置かれていても正しく動作することができる。


課題3 ジャンプ命令

FF200から機械語プログラムを置きなさい。途中には何も書かなくてもよい。
ff200にff300へのジャンプ命令jmpを置き,ff300にff310へのジャンプ命令jmpを置き,
さらにff310にff280へのジャンプ命令braを置き,ff280にff280へのジャンプ命令braを置く。

作成したプログラム本体を報告に載せなさい。

ff200から1命令ごと実行させた場合に,プログラムカウンタがどのように変化してゆくか,
観察して,報告しなさい。

ジャンプ命令とプログラムカウンタの関係を考察しなさい。
ジャンプ命令の代わりにジャンプ命令と同じ語長の命令があったとしたら,
その命令実行直後のプログラムカウンタの値はどうなるべきかを考察の文中に
盛り込みなさい。
またjmp命令とbra命令とでは,機械語に変換された時にどのようになっているのか比較して
考察の文中に盛り込みなさい。特にbra命令では値も変換されているが,その規則を見つけ出
し,考察の文中に盛り込みなさい。
(mon1ex03.txt)

 

4(補) 条件ジャンプ命令とCCR(コンディションコードレジスタ)

jmpやbraは「無条件ジャンプ命令」と呼ばれる。これらに対して,ある条件が成り立つときだけ, ジャンプする命令は「条件ジャンプ命令」である。
ある条件とは直前の命令の作業結果がゼロになったとか,負になったとかという内容であり,これらはコンディションコードレジスタCCRに保存されている。
命令が行われるたびにコンディションコードレジスタの内容は変化する。

コンディションコードレジスタ(8ビット:16進2ケタ)の値もr命令で表示される。

PC=000000 CCR=80:I....... SP=000FFF00
ER0=00000000 ER1=00000000 ER2=00000000 ER3=00000000
ER4=00000000 ER5=00000000 ER6=00000000 ER7=000FFF00

この赤い字のところがCCRであり,16進表示2ケタと各ビットが表示されている。
この表示では最上位ビットが 1で残りの7ビットは0であることを示している。
コンディションコードレジスタの各ビットの意味はマニュアルで調べること。
ここでは第2ビット(下から3つ目のビット)に着目する。
このビットはゼロフラグと呼ばれており,命令の結果が0になるとゼロフラッグは1になるように動作する。
(通常はZフラグは0である。)
ゼロフラグが1になると
 CCR=84:I....Z.. 
のように表示される。(CCR=84:10000100というのは不親切なのでIとZを表示している。)

次のプログラムを動かして動作を確かめてみよう。

: a ff200
FF200 > mov.b #03:8,r0l
FF202 > mov.b #00:8,r0h
FF204 > add.b #10:8,r0h
FF206 > dec.b r0l
FF208 > bne ff204:8
FF20A > mov.b r0h,r1l
FF20C > nop
FF20E > .
: da ff200 ff20c
<ADDR> <CODE> <MNEMONIC> <OPERAND>
FF200 F803 MOV.B #H'03:8,R0L
FF202 F000 MOV.B #H'00:8,R0H
FF204 8010 ADD.B #H'10:8,R0H
FF206 1A08 DEC.B R0L
FF208 46FA BNE FF204:8
FF20A 0C09 MOV.B R0H,R1L
FF20C 0000 NOP


R0L(8bitレジスタ)に3を保存
R0H(同上)に0を保存
R0Hに0x10を加える
R0Lを1減らす(R0L-- decriment)
Branch Not Equal Zero
   直前の演算がゼロでなかったらジャンプ
   実際には,ゼロフラグがnot1でジャンプ
nop は no operation 何もしないという意味


上記のプログラムは次のようなC言語のdo-whileの構文になっている

int x=3;
int y=0;
int z;
do {
    y+=0x10;
    x--;
} while (0<x);
z=y;

ただし
変数は次のように対応している
x:R0L
y:R0H
z:R1L


機械語プログラムを動作させます。

: r
PC=000000 CCR=80:I....... SP=000FFF00
ER0=00000000 ER1=00000000 ER2=00000000 ER3=00000000
ER4=00000000 ER5=00000000 ER6=00000000 ER7=000FFF00
: .pc
PC=000000 ? ff200
CCR=80 ? .
: r
PC=0FF200 CCR=80:I....... SP=000FFF00
ER0=00000000 ER1=00000000 ER2=00000000 ER3=00000000
ER4=00000000 ER5=00000000 ER6=00000000 ER7=000FFF00
: s
PC=0FF202 CCR=80:I....... SP=000FFF00
ER0=00000003 ER1=00000000 ER2=00000000 ER3=00000000
ER4=00000000 ER5=00000000 ER6=00000000 ER7=000FFF00
FF200 F803 MOV.B #H'03:8,R0L
: s
PC=0FF204 CCR=84:I....Z.. SP=000FFF00
ER0=00000003 ER1=00000000 ER2=00000000 ER3=00000000
ER4=00000000 ER5=00000000 ER6=00000000 ER7=000FFF00
FF202 F000 MOV.B #H'00:8,R0H
: s
PC=0FF206 CCR=80:I....... SP=000FFF00
ER0=00001003 ER1=00000000 ER2=00000000 ER3=00000000
ER4=00000000 ER5=00000000 ER6=00000000 ER7=000FFF00
FF204 8010 ADD.B #H'10:8,R0H
: s
PC=0FF208 CCR=80:I....... SP=000FFF00
ER0=00001002 ER1=00000000 ER2=00000000 ER3=00000000
ER4=00000000 ER5=00000000 ER6=00000000 ER7=000FFF00
FF206 1A08 DEC.B R0L
: s
PC=0FF204 CCR=80:I....... SP=000FFF00
ER0=00001002 ER1=00000000 ER2=00000000 ER3=00000000
ER4=00000000 ER5=00000000 ER6=00000000 ER7=000FFF00
FF208 46FA BNE FF204:8
: s
PC=0FF206 CCR=80:I....... SP=000FFF00
ER0=00002002 ER1=00000000 ER2=00000000 ER3=00000000
ER4=00000000 ER5=00000000 ER6=00000000 ER7=000FFF00
FF204 8010 ADD.B #H'10:8,R0H
: s
PC=0FF208 CCR=80:I....... SP=000FFF00
ER0=00002001 ER1=00000000 ER2=00000000 ER3=00000000
ER4=00000000 ER5=00000000 ER6=00000000 ER7=000FFF00
FF206 1A08 DEC.B R0L
: s
PC=0FF204 CCR=80:I....... SP=000FFF00
ER0=00002001 ER1=00000000 ER2=00000000 ER3=00000000
ER4=00000000 ER5=00000000 ER6=00000000 ER7=000FFF00
FF208 46FA BNE FF204:8
: s
PC=0FF206 CCR=80:I....... SP=000FFF00
ER0=00003001 ER1=00000000 ER2=00000000 ER3=00000000
ER4=00000000 ER5=00000000 ER6=00000000 ER7=000FFF00
FF204 8010 ADD.B #H'10:8,R0H
: s
PC=0FF208 CCR=84:I....Z.. SP=000FFF00
ER0=00003000 ER1=00000000 ER2=00000000 ER3=00000000
ER4=00000000 ER5=00000000 ER6=00000000 ER7=000FFF00
FF206 1A08 DEC.B R0L
: s
PC=0FF20A CCR=84:I....Z.. SP=000FFF00
ER0=00003000 ER1=00000000 ER2=00000000 ER3=00000000
ER4=00000000 ER5=00000000 ER6=00000000 ER7=000FFF00
FF208 46FA BNE FF204:8
: s
PC=0FF20C CCR=80:I....... SP=000FFF00
ER0=00003000 ER1=00000030 ER2=00000000 ER3=00000000
ER4=00000000 ER5=00000000 ER6=00000000 ER7=000FFF00
FF20A 0C09 MOV.B R0H,R1L


各レジスタの確認


プログラムカウンタのセット


PCの確認




3→R0L




0→R0H
このとき,命令の結果はR0Hを0にしたので
Zフラグが立った(1になった)
プログラム上は意味はない

R0H+R0H→R0H
Zフラグはもとに戻った



R0L--
まだZフラグは立たない



Zフラグは立っていないのでFF204にジャンプ




R0H + R0H→R0H




R0L--
まだZフラグは立たない



Zフラグは立っていないのでFF204にジャンプ




R0H + R0H→R0H




R0L--
R0LがゼロになったのでZフラグが立った



Zフラグが立ったのでジャンプしない
で次の命令(FF20Aの命令)に進んだ
ジャンプ命令ではZフラグは変化しない




ここでは,ZフラグとBNEの関係について述べたが,加算や減算などの演算結果が負になるとNフラグが立ち,加算や減算などの演算結果がオーバーフ ローするとVフラグが立ち,シフト演算などでキャリにビットがあふれるとCフラグが立ち,それぞれの条件でジャンプする命令がある。それらのジャンプ命令 はマニュアルにおいては,「Bcc」で見つけることができる。


課題4 条件ジャンプ

上記のプログラムを変更して1から10まで和を求めるプログラムにしなさい。

作成したプログラム本体を報告に載せなさい。

答えは55(0x37)になるはず。全作業結果を示しなさい。
(mon1ex04.txt)
答えが正しく求められているところを指し示しなさい。



5. スタックとpush命令/pop命令

スタックのイメージは「マイクロコンピュータH8の構成と機械語プログラムの動作」の該当箇所を参照すること

スタックはレジスタ内容の一時保管に使われるメモリ(当然RAM領域)の一部である。

保管データは,スタック用のメモリの後ろから前(若いアドレス)に向かって保管される。
メモリ中のどこをスタックとして使用中なのかを示しているのがスタックポインタである。

最初にER7(SPの働きをしている)に値を設定し,どこをスタックとして使うかを決めている。
スタックポインタは現在までにスタックとして使われているメモリの一番前の(一番若い)アドレスを指している。

目的 push命令とpop命令により,指定されたレジスタの内容がメモリのスタック領域に格納され,
またレジスタに書き戻されること,スタックポインタが変化することを確認する。
例題4

FF200から機械語プログラムを置きなさい。
スタックポインタにFFF00をセットする。
レジスタER0に12344321をセットする。
レジスタER0をpushする。 (ER0の内容がスタック内のスタックポインタが指す場所に保存される)
レジスタER1にpopする。 (スタックに最後に保存された内容がER1に載せられる)
1命令ずつ実行すると
ER0,ER1,PC(プログラムカウンタ)SP(スタックポインタ,ER7のこと。
表示ではSPとER7が別物のように表示されているが,内容は常に同一の値になっている),
FFEF0からFFF00までのメモリの様子
はどうなるか,観察して,報告しなさい。

push命令 指定されたレジスタの内容を,スタック領域のスタックポインタの指すメモリに,退避させる。
pop命令 スタック領域のスタックポインタの指すメモリの内容を,指定されたレジスタに,取り戻す。

使い終わったスタックエリアは,他のプログラムが勝手に使うことがあるので,身に覚えのない値が入っていることがある。
(下の実行例の最終表示では,たまたま前の値が残っているが,常にこのようになるとは限らない)

実行例 : a ff200
  FF200   >  mov.l #fff00:32,er7
  FF206   >  mov.l #12384521:32,er0
  FF20C   >  push.l er0
  FF210   >  pop.l er1
  FF214   >  .
: da ff200 ff210
  <ADDR>  <CODE>                <MNEMONIC> <OPERAND>
  FF200   7A07000FFF00          MOV.L      #H'000FFF00:32,ER7
  FF206   7A0012384521          MOV.L      #H'12384521:32,ER0
  FF20C   01006DF0              PUSH.L     ER0
  FF210   01006D71              POP.L      ER1
: .pc
  PC=0FF300  ?  ff200
  CCR=80  ?  .
: d ffef0 fff00
  <ADDR>                  <  D  A  T  A  >                     < ASCII CODE >
  FFEF0   A0 00 FF DF 00 00 D7 FE  80 80 29 B0 00 0F F3 02   "..........)....."
  FFF00   00                                                 "."
: r
  PC=0FF200  CCR=80:I.......  SP=000FFF10
  ER0=00000066  ER1=00000031  ER2=00000000  ER3=00000000
  ER4=00000000  ER5=00000000  ER6=00000000  ER7=000FFF10
: s
  PC=0FF206  CCR=80:I.......  SP=000FFF00
  ER0=00000066  ER1=00000031  ER2=00000000  ER3=00000000
  ER4=00000000  ER5=00000000  ER6=00000000  ER7=000FFF00
  FF200   7A07000FFF00          MOV.L      #H'000FFF00:32,ER7
: s
  PC=0FF20C  CCR=80:I.......  SP=000FFF00
  ER0=12384521  ER1=00000031  ER2=00000000  ER3=00000000
  ER4=00000000  ER5=00000000  ER6=00000000  ER7=000FFF00
  FF206   7A0012344321          MOV.L      #H'12344321:32,ER0
: s
  PC=0FF210  CCR=80:I.......  SP=000FFEFC
  ER0=12384521  ER1=00000031  ER2=00000000  ER3=00000000
  ER4=00000000  ER5=00000000  ER6=00000000  ER7=000FFEFC
  FF20C   01006DF0              PUSH.L     ER0
: d ffef0 fff00
  <ADDR>                  <  D  A  T  A  >                     < ASCII CODE >
  FFEF0   A0 00 FF DF 80 80 29 B0  00 0F F2 12 12 38 45 21   "......)......8E!"
  FFF00   00                                                 "."
: s
  PC=0FF214  CCR=80:I.......  SP=000FFF00
  ER0=12384521  ER1=12384521  ER2=00000000  ER3=00000000
  ER4=00000000  ER5=00000000  ER6=00000000  ER7=000FFF00
  FF210   01006D71              POP.L      ER1
: d ffef0 fff00
  <ADDR>                  <  D  A  T  A  >                     < ASCII CODE >
  FFEF0   A0 00 FF DF 80 80 29 B0  00 0F F2 12 12 38 45 21   "......)......8E!"
  FFF00   00                                                 "."
:
















初期状態の確認



スタックポインタが
FFF10
を指している。

スタックポインタが
FFF00
を指すように
なった。






スタックポインタが
4減って,FFEFC
を指すようになり,
ER0の値が
FFEFCから
FFEFFに保存
された。



スタックポインタが
FFF00に戻り,
ER1にFFEFCから
FFEFFの内容が
保存された。

H8命令ニーモニクの説明マニュアル 学内高速読み取りバッファより


最初の命令でスタックポインタに0FFF00を設定しているので,スタック領域は0FFEFFから若いアドレスに向かって設定されたことになる。
最初の時点でスタックポインタに0FFF00が設定されているが,このアドレスはスタック領域の外部になっていることに注意しよう。
次に4バイトがpushされると,スタックポインタは4小さくなり,0FFEFCになる。
この時スタック領域では0FFEFCから0FFEFFの4バイトにpushされた値が格納されているのがわかる。
マイクロコンピュータH8の構成と機械語プログラムの動作」の「6.スタックとスタックポインタ」を参照すること。

動作をまとめると次のようになっている。

・push.l er0
最初にSPの値が4減少する.そして減少したSPの値を先頭
アドレスとするメモリ領域(4バイト)にレジスタer0の
値が保存される.

・pop.l er2
現在のSPの値を先頭アドレスとするメモリ領域(4バイト)
にある値をレジスタer2に保存する.そしてSPの値は4増加
する.

使用していないスタック領域のメモリ内容はだれも手をつけないので,本当は変化しないはずであるが,
モニタプログラムがこっそりと使っているため変化している。これは無視すること。


課題5 push命令・pop命令とスタックの変化,スタックポインタの動き

FF200から機械語プログラムを置きなさい。
スタックポインタにFFF00をセットする。
レジスタER0にff0088ccをセットする。
レジスタER0をpushする。
レジスタER2にpopする。

作成したプログラム本体を報告に載せなさい。

1命令ずつ実行すると
ER0,ER2,PC(プログラムカウンタ)SP(スタックポインタ,ER7と同じ),FFEF0からFFF00までのメモリの様子
はどうなるか,観察して,全実行結果を報告しなさい。

push命令実行直前のスタックポインタの値,実行直後のスタックポインタの値,どのレジスタの内容がどこのアドレスのメモリに格納されたのか,
(ここでは4バイトの値のはずなので,何番地から何番地までのメモリに格納されたのか),関連を考えて考察の文中 に盛り込みなさい。
pop命令実行直前のスタックポインタの値,実行直後のスタックポインタの値,どこのメモリの内容がどこのレジスタに書き戻されたか
(ここでは4バイトの値のはずなので,何番地から何番地までのメモリから書き戻されたのか),関連を考えて考察の文中に盛り込みなさい。

「push.l er0」によってなにが起こるのか,まとめに盛り込みなさい。
「pop.l er2」によってなにが起こるのか,まとめに盛り込みなさい。

(mon1ex05.txt)

 

6. スタックへのレジスタの退避と復帰

目的 レジスタの内容をスタック領域に退避させ,そのレジスタを別の用途に使用した後,
スタック領域に保存された内容をレジスタに戻す作業を確認する。
例題5

FF200から機械語プログラムを置きなさい。
スタックポインタにFFF00をセットする。
レジスタER0に12344321をセットする。
レジスタER1に34566543をセットする。
レジスタER0をpushする。
レジスタER1をpushする。
レジスタER0に0をセットする。(ER0を別用途に使ったと想定する)
レジスタER1に0をセットする。(ER1を別用途に使ったと想定する)
レジスタER1にpopする。
レジスタER0にpopする。
1命令ずつ実行すると
ER0,ER1,PC(プログラムカウンタ)SP(スタックポインタ,ER7と同じ),FFEF0からFFF00までの
メモリの様子はどうなるか,観察して,報告しなさい。

実行例 : a ff200
  FF200   >  mov.l #fff00:32,er7
  FF206   >  mov.l #12344321:32,er0
  FF20C   >  mov.l #34566543:32,er1
  FF212   >  push.l er0
  FF216   >  push.l er1
  FF21A   >  mov.l #0:32,er0
  FF220   >  mov.l #0:32,er1
  FF226   >  pop.l er1
  FF22A   >  pop.l er0
  FF22E   >  .
: da ff200 ff22a
  <ADDR>  <CODE>                <MNEMONIC> <OPERAND>
  FF200   7A07000FFF00          MOV.L      #H'000FFF00:32,ER7
  FF206   7A0012344321          MOV.L      #H'12344321:32,ER0
  FF20C   7A0134566543          MOV.L      #H'34566543:32,ER1
  FF212   01006DF0              PUSH.L     ER0
  FF216   01006DF1              PUSH.L     ER1
  FF21A   7A0000000000          MOV.L      #H'00000000:32,ER0
  FF220   7A0100000000          MOV.L      #H'00000000:32,ER1
  FF226   01006D71              POP.L      ER1
  FF22A   01006D70              POP.L      ER0
: d ffef0 fff00
  <ADDR>                  <  D  A  T  A  >                     < ASCII CODE >
  FFEF0   A0 00 FF DF 80 80 29 B0  80 80 29 B0 00 0F F2 16   "......)...)....."
  FFF00   00                                                 "."
: .pc
  PC=0FF212  ?  ff200
  CCR=80  ?  .
: .er0
  ER0=12344321  ?  0
  ER1=34566543  ?  0
  ER2=00000000  ?  .
: r
  PC=0FF200  CCR=80:I.......  SP=000FFF00
  ER0=00000000  ER1=00000000  ER2=00000000  ER3=00000000
  ER4=00000000  ER5=00000000  ER6=00000000  ER7=000FFF00
: s
  PC=0FF206  CCR=80:I.......  SP=000FFF00
  ER0=00000000  ER1=00000000  ER2=00000000  ER3=00000000
  ER4=00000000  ER5=00000000  ER6=00000000  ER7=000FFF00
  FF200   7A07000FFF00          MOV.L      #H'000FFF00:32,ER7
: s
  PC=0FF20C  CCR=80:I.......  SP=000FFF00
  ER0=12344321  ER1=00000000  ER2=00000000  ER3=00000000
  ER4=00000000  ER5=00000000  ER6=00000000  ER7=000FFF00
  FF206   7A0012344321          MOV.L      #H'12344321:32,ER0
: s
  PC=0FF212  CCR=80:I.......  SP=000FFF00
  ER0=12344321  ER1=34566543  ER2=00000000  ER3=00000000
  ER4=00000000  ER5=00000000  ER6=00000000  ER7=000FFF00
  FF20C   7A0134566543          MOV.L      #H'34566543:32,ER1
: s
  PC=0FF216  CCR=80:I.......  SP=000FFEFC
  ER0=12344321  ER1=34566543  ER2=00000000  ER3=00000000
  ER4=00000000  ER5=00000000  ER6=00000000  ER7=000FFEFC
  FF212   01006DF0              PUSH.L     ER0
: d ffef0 fff00
  <ADDR>                  <  D  A  T  A  >                     < ASCII CODE >
  FFEF0   A0 00 FF DF 80 80 29 B0  00 0F F2 18 12 34 43 21   "......)......4C!"
  FFF00   00                                                 "."
: s
  PC=0FF21A  CCR=80:I.......  SP=000FFEF8
  ER0=12344321  ER1=34566543  ER2=00000000  ER3=00000000
  ER4=00000000  ER5=00000000  ER6=00000000  ER7=000FFEF8
  FF216   01006DF1              PUSH.L     ER1
: d ffef0 fff00
  <ADDR>                  <  D  A  T  A  >                     < ASCII CODE >
  FFEF0   80 80 29 B0 00 0F F2 1C  34 56 65 43 12 34 43 21   "..).....4VeC.4C!"
  FFF00   00                                                 "."
: s
  PC=0FF220  CCR=84:I....Z..  SP=000FFEF8
  ER0=00000000  ER1=34566543  ER2=00000000  ER3=00000000
  ER4=00000000  ER5=00000000  ER6=00000000  ER7=000FFEF8
  FF21A   7A0000000000          MOV.L      #H'00000000:32,ER0
: s
  PC=0FF226  CCR=84:I....Z..  SP=000FFEF8
  ER0=00000000  ER1=00000000  ER2=00000000  ER3=00000000
  ER4=00000000  ER5=00000000  ER6=00000000  ER7=000FFEF8
  FF220   7A0100000000          MOV.L      #H'00000000:32,ER1
: s
  PC=0FF22A  CCR=80:I.......  SP=000FFEFC
  ER0=00000000  ER1=34566543  ER2=00000000  ER3=00000000
  ER4=00000000  ER5=00000000  ER6=00000000  ER7=000FFEFC
  FF226   01006D71              POP.L      ER1
: s
  PC=0FF22E  CCR=80:I.......  SP=000FFF00
  ER0=12344321  ER1=34566543  ER2=00000000  ER3=00000000
  ER4=00000000  ER5=00000000  ER6=00000000  ER7=000FFF00
  FF22A   01006D70              POP.L      ER0
:

H8命令ニーモニクの説明マニュアル 学内高速読み取りバッファより

マイクロコンピュータH8の構成と機械語プログラムの動作」の「6.スタックとスタックポインタ」を参照すること。



課題6 スタックへのレジスタの退避と復帰

FF200から機械語プログラムを置きなさい。
スタックポインタにFFF00をセットする。
レジスタER0に1122eeffをセットする。
レジスタER1にaabb4477をセットする。
レジスタER2に34567890をセットする。
レジスタER0をpushする。
レジスタER1をpushする。
レジスタER2をpushする。
レジスタER0に0をセットする。(ER0を別用途に使ったと考える)
レジスタER1に0をセットする。(ER1を別用途に使ったと考える)
レジスタER2に0をセットする。(ER2を別用途に使ったと考える)
レジスタER2にpopする。
レジスタER1にpopする。
レジスタER0にpopする。

作成したプログラム本体を報告に載せなさい。

1命令ずつ実行すると
ER0,ER1,ER2,PC(プログラムカウンタ)SP(スタックポインタ,ER7と同じ),FFEF0からFFF00までのメモリの様子はどうなるか,
観察して,全実行結果を報告しなさい。
各 push命令実行直前のスタックポインタの値,実行直後のスタックポインタの値,
どのレジスタの内容がどこのアドレスのメモリに格納されたのか
(ここでは 4バイトの値のはずなので,何番地から何番地までのメモリに格納されたのか),
関連を考えて考察の文中に盛り込みなさい。
各pop命令実行直前のスタックポインタの値,実行直後のスタックポインタの値,
どこのメモリの内容がどこのレジスタに書き戻されたか
(ここでは4バイトの値のはずなので,何番地から何番地までのメモリから書き戻されたのか),
関連を考えて考察の文中に盛り込みなさい。
(mon1ex06.txt)

 

7. サブルーチンコールとサブルーチンからのリターン

サブルーチンコールとサブルーチンからのリターンのイメージは
マイクロコンピュータH8の構成と機械語プログラムの動作」の該当箇所を参照すること
C言語の関数呼び出しと同じ機能(実際には全く同じもの)
サブルーチンコールの時には,戻り番地がスタックに保存され,PC(プログラムカウンタ)の値を
サブルーチンの先頭に設定してジャンプし,サブルーチンから戻るときにはスタックに保存されて
いるアドレスをPCに設定してジャンプして,サブルーチン呼び出し側の先ほどの続きの作業を行っ
ていることを確認しよう。

目的 サブルーチンコールとサブルーチンからのリターンについて,スタックの仕掛けを用いて,戻り番地を保存しているところを確認する。
例題6

FF200から機械語プログラムを置きなさい。
スタックポインタにFFF00をセットする。
FF800番地の2byteデータをレジスタR0に載せる
サブルーチンをコールする
戻ってきたらレジスタR0の値をFF802番地の2byteデータとして保存
そして無限ループ
ただし,サブルーチンはsll命令(shift left logical,指定したレジスタの全データを左に1ビット分ずらす
)を2回使い
レジスタR0の値を左に2つシフト(4倍になる)させ
リターンする
1命令ずつ実行すると
ER0,ER1,ER2,PC(プログラムカウンタ)SP(スタックポインタ,ER7と同じ),FFEF0からFFF00までのメモリの様子
はどうなるか,観察して,報告しなさい。

アセンブル命令でサブルーチンコールを書くとき,まだサブルーチンのアドレスはわからないので,
推定値を書いておいて,サブルーチン本体を書いた後にアドレスが確定するので,後から書きなおすとよい。★

bsr命令 (
branch subroutine) 指定したアドレスから始まるサブルーチンにジャンプする
rts命令 (return from subroutine) サブルーチンの終わりにおかれ,サブルーチンを呼び出したところに戻る

実行例 : a ff200
  FF200   >  mov.l #fff00:32,er7
  FF206   >  mov.w @ff800:24,r0
  FF20C   >  bsr ff210:8
  FF20E   >  mov.w r0,@ff802:24
  FF214   >  bra ff214:8
  FF216   >  shll.w r0
  FF218   >  shll.w r0
  FF21A   >  rts
  FF21C   >  .
: a ff20c
  FF20C   >  bsr ff216:8
  FF20E   >  .
: da ff200 ff21c
  <ADDR>  <CODE>                <MNEMONIC> <OPERAND>
  FF200   7A07000FFF00          MOV.L      #H'000FFF00:32,ER7
  FF206   6B20000FF800          MOV.W      @H'FF800:24,R0
  FF20C   5508                  BSR        FF216:8
  FF20E   6BA0000FF802          MOV.W      R0,@H'FF802:24
  FF214   40FE                  BRA        FF214:8
  FF216   1010                  SHLL.W     R0
  FF218   1010                  SHLL.W     R0
  FF21A   5470                  RTS       
  FF21C   0001                  .DATA.W    H'0001
: d ffef0 fff00
  <ADDR>                  <  D  A  T  A  >                     < ASCII CODE >
  FFEF0   A0 00 FF DF 00 00 D7 FE  00 00 BF DF 41 00 BF FF   "............A..."
  FFF00   00                                                 "."
: d ff800 ff80f
  <ADDR>                  <  D  A  T  A  >                     < ASCII CODE >
  FF800   00 00 DF EF 00 00 FF 7F  00 80 FF FF 00 00 FF ED   "................"
: m ff800
  FF800   00  ?  02
  FF801   00  ?  03
  FF802   DF  ?  .
: d ff800 ff80f
  <ADDR>                  <  D  A  T  A  >                     < ASCII CODE >
  FF800   02 03 DF EF 00 00 FF 7F  00 80 FF FF 00 00 FF ED   "................"
: .pc
  PC=000000  ?  ff200
  CCR=80  ?  .
: r
  PC=0FF200  CCR=80:I.......  SP=00FFFF10
  ER0=00000000  ER1=00000000  ER2=00000000  ER3=00000000
  ER4=00000000  ER5=00000000  ER6=00000000  ER7=00FFFF10
: s
  PC=0FF206  CCR=80:I.......  SP=000FFF00
  ER0=00000000  ER1=00000000  ER2=00000000  ER3=00000000
  ER4=00000000  ER5=00000000  ER6=00000000  ER7=000FFF00
  FF200   7A07000FFF00          MOV.L      #H'000FFF00:32,ER7
: s
  PC=0FF20C  CCR=80:I.......  SP=000FFF00
  ER0=00000203  ER1=00000000  ER2=00000000  ER3=00000000
  ER4=00000000  ER5=00000000  ER6=00000000  ER7=000FFF00
  FF206   6B20000FF800          MOV.W      @H'FF800:24,R0
: s
  PC=0FF216  CCR=80:I.......  SP=000FFEFC
  ER0=00000203  ER1=00000000  ER2=00000000  ER3=00000000
  ER4=00000000  ER5=00000000  ER6=00000000  ER7=000FFEFC
  FF20C   5508                  BSR        FF216:8
: d ffef0 fff00
  <ADDR>                  <  D  A  T  A  >                     < ASCII CODE >
  FFEF0   A0 00 FF DF 80 80 29 B0  00 0F F2 18 00 0F F2 0E   "......)........."
  FFF00   00                                                 "."
: s
  PC=0FF218  CCR=80:I.......  SP=000FFEFC
  ER0=00000406  ER1=00000000  ER2=00000000  ER3=00000000
  ER4=00000000  ER5=00000000  ER6=00000000  ER7=000FFEFC
  FF216   1010                  SHLL.W     R0
: s
  PC=0FF21A  CCR=80:I.......  SP=000FFEFC
  ER0=0000080C  ER1=00000000  ER2=00000000  ER3=00000000
  ER4=00000000  ER5=00000000  ER6=00000000  ER7=000FFEFC
  FF218   1010                  SHLL.W     R0
: s
  PC=0FF20E  CCR=80:I.......  SP=000FFF00
  ER0=0000080C  ER1=00000000  ER2=00000000  ER3=00000000
  ER4=00000000  ER5=00000000  ER6=00000000  ER7=000FFF00
  FF21A   5470                  RTS       
: s
  PC=0FF214  CCR=80:I.......  SP=000FFF00
  ER0=0000080C  ER1=00000000  ER2=00000000  ER3=00000000
  ER4=00000000  ER5=00000000  ER6=00000000  ER7=000FFF00
  FF20E   6BA0000FF802          MOV.W      R0,@H'FF802:24
: d ff800 ff80f
  <ADDR>                  <  D  A  T  A  >                     < ASCII CODE >
  FF800   02 03 08 0C 00 00 FF 7F  00 80 FF FF 00 00 FF ED   "................"
:



とりあえずff210にしておく

無限ループ,ここまでがmain
ff216からサブルーチン

ReTurn from Subroutine

サブルーチンのアドレスが
ff216だとわかったので
書き直し











スタック領域の確認



データ領域の確認


データの設定



データ領域の確認





















サブルーチンコール
スタックに戻り番地を積む

スタックに戻り番地が
積まれていることの確認














ReTurn from Subroutine
スタックから戻り番地を
プログラムカウンタに取
り込んだ



解説

 人間は,プログラムリストを見て,「ここにサブルーチンコール命令があるから,次はサブルーチン側にプログラム実行の流れが変わって・・・,
最後にリターン命令があるから,先ほどのサブルーチンコール命令の次の命令に戻る」といように理解する。
しかし,CPUはプログラムリストを見てこれらの2回のジャンプするわけではない。

 サブルーチンコール命令内に,ジャンプすべきサブルーチン先頭アドレスが埋め込まれており,
その情報をもとに,ジャンプすべきサブルーチン先頭アドレスをPC(プログラムカウンタ)に書き込んでいるだけである。(ここまではジャンプ命令と同じ)
その結果,CPUの次に行うべき機械語命令がサブルーチンの先頭アドレスになってしまい,
 人間から見ると,作業の流れがジャンプしたように見えることになる。
またサブルーチンコール命令が実行されるとき,同時に本来のPC(プログラムカウンタ)の値をスタックに保存する。
このことはスタックポインタが変化し,スタック領域に本来のPC(プログラムカウンタ,サブルーチンコール命令の次の命令のアドレス)
の値が書き込まれていることから確認できる。

 最後にリターン命令になると(リターン命令には戻るべきアドレス情報は含まれていない),
スタックから戻るべきアドレスを取り出してPC(プログ ラムカウンタ)に格納し,
サブルーチンコール命令の次の命令のアドレスにジャンプすることになる。このこともスタックポインタが変化しているので確認でき る。

  ところで,サブルーチンコール命令では,戻るべき番地をスタックに保存している。
サブルーチン内でさらに別なサブルーチンを呼び出す場合でも,戻るべき番地をスタックに保存する。
さらにサブルーチンを呼び出しても同様である。
これは,スタックがLastIn-FirstOut(最後に入れたものが最初に 取り出される)の性質を持っているからである。

 mainの最後のところは無限ループになっている。もしなにも書かなければ,mainの最後から続けてサブルーチン内に入ってしまう。

H8命令ニーモニクの説明マニュアル 学内高速読み取りバッファより


マイクロコンピュータH8の構成と機械語プログラムの動作」の「8.サブルーチンコールとリターン」を参照すること。


課題7 サブルーチンコールとサブルーチンからのリターン

FF200から機械語プログラムを置きなさい。
スタックポインタにFFF00をセットする。
FF800番地の2byteデータをレジスタR0に載せる
FF802番地の2byteデータをレジスタR1に載せる
サブルーチンをコールする
戻ってきたらレジスタR0の値をFF804番地の2byteデータとして保存
そして無限ループで何もしなくなる。

ただし,サブルーチンは
レジスタR0の値とR1の値の和を作りR0に載せ,
リターンする

作成したプログラム本体を報告に載せなさい。

1命令ずつ実行すると
ER0,ER1,ER2,PC(プログラムカウンタ)SP(スタックポインタ,ER7と同じ),FFEF0からFFF00までのメモリの様子
,FF800からFF80Fまでのメモリの様子
はどうなるか,観察して,全実行結果を報告しなさい。

以下のことを考察の文中に盛り込みなさい。
サブルーチンコール命令によって,プログラムカウンタの値はどのように変化したのか。
値およびその値の意味を示しなさい。
サブルーチンコール命令実行直後のプログラムカウンタの値はサブルーチンコール命令とどのような関係になっているか。
サブルーチンコール命令直前,直後のスタックポインタの値はどうであったか。
サブルーチンコール命令によって,スタック領域のどの番地(複数の番地が使われたはず)には何が格納されたのか。
値とその値の意味を答えなさい。
またサブルーチンから戻るべきアドレスはどこに書き込まれたのか,
スタックポインタの値との関連で考察しなさい。
サブルーチンからのリターン命令でプログラムカウンタの値が変化するが,
その仕組みはどうなっているのか,スタックポインタの値,プログラムカウンタとの関連で考察しなさい。

(mon1ex07.txt)

 


8. まとめ

8.1 機械語命令の実行

機械語命令はメモリ上に書かれている
PC(プログラムカウンタ)は次に実行すべき機械語命令が書かれているアドレスを指している
1つの機械語命令はPCの指しているメモリから読みだされ,命令の意味が解析され,実行される
1つの機械語命令の実行が終わると,PCの値はその機械語命令のバイト数だけ増加する
(次に実行すべき機械語命令の書かれているアドレスを指すようになる)

CPUがプログラムリストを見て,次の命令の存在するアドレスをPCに書き込むわけではない!

8.2 ジャンプ命令の実行
    プログラムの流れがジャンプしたように見える仕組み

通常,1つの機械語命令の実行が終わると,PC(プログラムカウンタ)の値はその機械語命令のバイト数だけ増加する
(次に実行すべき機械語命令の書かれているアドレスを指すようになる)はずである。
ジャンプ命令が実行されると,PCの値は「ジャンプ命令中に示されるアドレス」になり,プログラムリスト上の実行の流れが変わる。

8.3 スタックの操作
    明示的な変数を使わずに,レジスタの値をメモリ上に一時的に覚えておく仕組み

push(スタックへの保存)の動作は,スタックポインタの値を「保存すべきバイト数」だけ減少させ,スタックポインタの指すアドレス(メモリ上のある場所)に,指定したレジスタの値を保存する。
pop(スタックからの復帰)の動作は,スタックポインタの指すアドレス(メモリ上のある場所)に保存されている値を,指定したレジスタに書き戻し,その後スタックポインタの値を「書き戻したバイト数」だけ増やす。

8.4 サブルーチンコール命令の実行
    プログラムの流れがサブルーチンの先頭にジャンプしたように見え,サブルーチンからの戻り番地を覚えておく仕組み

通常,1つの機械語命令の実行が終わると,PC(プログラムカウンタ)の値はその機械語命令のバイト数だけ増加する
(次に実行すべき機械語命令の書かれているアドレスを指すようになる)はずである。
サブルーチンコール命令が実行されると,PCの値はサブルーチンコール命令中に書いてあるアドレスになる。
そして,本来PCに入っているはずの値(本来,次に実行すべき機械語命令の書かれているアドレス)はスタックに保存される。

スタックへの保存とは,スタックポインタの値を「保存すべきバイト数」だけ減少させ,スタックポインタの指すアドレスに,保存すべき値を保存する。

8.5 サブルーチンリターン命令の実行
     サブルーチンから,サブルーチンコールした位置に戻る仕組み

サブルーチンリターン命令が実行されるとPC(プログラムカウンタ)には,スタックに覚えられていたアドレスが書き戻される。
すなわち,サブルーチンコール命令の次のアドレスがPCの値となる。