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

Copyright(C)29Dec2010
since 1Aug2003
coskx


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

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

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

このファイルを解凍すると「trial4」のフォルダが出てくるので,
作業用フォルダとして使います。
((本校)LANからのみ試用のためアクセスできます。)
4J電子計算機IIの授業ではこれを使います

H8機械語命令ニーモニクの説明マニュアル
((本校)LANからのみアクセスできます。)

注意
この文書で扱っているAsm2Mon.cmdはWindows2000,WindowsXP,WindowsVista,Windows7で使用可能です。

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命令実行
























実行結果メモリの確認

 

補足説明 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つの機械語命令を実行すると,プログラムカウンタの値が増加するが,増分値は
何に依存するのかを考察に盛り込みなさい。
(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
:
実行例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

解説

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

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になるように動作する。ゼロフラグが1になると
 CCR=84: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でジャンプ



上記のプログラムは次のような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フラグは変化しない



課題

上記のプログラムを変更して1から10まで和を求めるプログラムにしなさい。
答えは55(0x37)になるはず。実行結果を示しなさい。

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

 

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

スタックはレジスタ内容の一時保管に使われるメモリ(当然RAM領域)の一部である。
保管データは,スタック用のメモリの後ろから前(若いアドレス)に向かって保管される。
メモリ中のどこがスタックとして使われているのかを示しているのがスタックポインタである。
最初にFR7(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 #12344321: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   7A0012344321          MOV.L      #H'12344321: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=12344321  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=12344321  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 34 43 21   "......)......4C!"
  FFF00   00                                                 "."
: s
  PC=0FF214  CCR=80:I.......  SP=000FFF00
  ER0=12344321  ER1=12344321  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 34 43 21   "......)......4C!"
  FFF00   00                                                 "."
:

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


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

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

課題4

FF200から機械語プログラムを置きなさい。
スタックポインタにFFF00をセットする。
レジスタER0にff0088ccをセットする。
レジスタER0をpushする。
レジスタER2にpopする。
1命令ずつ実行すると
ER0,ER2,PC(プログラムカウンタ)SP(スタックポインタ,ER7と同じ),FFEF0からFFF00までのメモリの様子
はどうなるか,観察して,報告しなさい。
push命令実行直前のスタックポインタの値,実行直後のスタックポインタの値,どのレジスタの内容がどこのアドレスのメモリに格納されたのか(ここでは4バイトの値のはずなので,何番地から何番地までのメモリに格納されたのか)を関連を考えて考察しなさい。
pop命令実行直前のスタックポインタの値,実行直後のスタックポインタの値,どこのメモリの内容がどこのレジスタに書き戻されたか(ここでは4バイトの値のはずなので,何番地から何番地までのメモリから書き戻されたのか)を関連を考えて考察しなさい。
(mon1ex04.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
:

解説

 人間は,プログラムリストを見て,「ここにサブルーチンコール命令があるから,次はこっちにプログラム実行の流れが変わって・・・,最後にリターン命令があるから,先ほどのサブルーチンコール命令の次の命令に戻る」といように理解するが,CPUはプログラムリストを見てこれらの2回のジャンプするわけではない。
 サブルーチンコール命令内に,ジャンプすべきアドレスに関する情報が埋め込まれており,その情報をもとに,ジャンプすべきサブルーチン先頭アドレスをPC(プログラムカウンタ)に書き込んでいるだけである。その結果,CPUの次に行うべき機械語命令が離れた場所になってしまい,人間から見ると,作業の流れがジャンプしたように見えることになる。またサブルーチンコール命令は,同時に本来のPC(プログラムカウンタ)の値をスタックに保存する。
 最後にリターン命令になると(リターン命令には戻るべきアドレス情報は含まれていない),スタックから戻るべきアドレスを取り出してPC(プログラムカウンタ)に格納し,サブルーチンコール命令の次の命令のアドレスにジャンプすることになる。
 ところで,サブルーチンコール命令では,戻るべき番地をスタックに保存しているが。サブルーチン内でさらに別なサブルーチンを呼び出す場合でも,戻るべき番地をスタックに保存する。さらにサブルーチンを呼び出しても同様である。これは,スタックがLastIn-FirstOut(最後に入れたものが最初に取り出される)の性質を持っているからである。

 

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

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

 

課題5

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バイトの値のはずなので,何番地から何番地までのメモリから書き戻されたのか)を関連を考えて考察しなさい。
(mon1ex05.txt)

 

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

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
ここからサブルーチン


ReTurn from Subroutine

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











スタック領域の確認



データ領域の確認


データの設定



データ領域の確認





















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

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


















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



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


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

課題6

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までのメモリの様子
はどうなるか,観察して,報告しなさい。

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

(mon1ex06.txt)

 


8. まとめ

8.1 機械語命令の実行

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

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

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

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

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

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

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

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

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