基礎実験1 UNIX・アセンブラ実習 第4

2007419

実習内容

エミュレータ(m68k-emu)を使って,いくつかの簡単なプログラム実行を試しながら,アセンブラのプログラムに慣れることを行う.エミュレータを使って,分岐命令における各種レジスタとメモリの値の変化を注意深く観察し,CPUの振る舞いについて理解を深めていく.

 

1.     エミュレータ(m68k-emu)の実行画面

 

CPU内の

各種レジスタの値(刻々と変化する

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


エミュレータ(m68k-emu) を使って,68000 CPUの全てのレジスタ(プログラムカウンタやステータスレジスタも)を観察できます.また,任意のメモリアドレスのデータの値を観察することもできます.この機能は,68000 CPU の振る舞いを学習するのに役立ちます.また,作成したプログラム中のバグの発見にも役立ちます.

 

 

 

16ビット幅

 

32ビット幅

 

PC: プログラムカウンタ

 

A7, A7’: スタックポインタ

 

SR: ステータスレジスタ

 

A0A6: データレジスタ

 

D0D7: データレジスタ

 

 

レジスタの値は,16進数の8桁(つまり32ビット=4バイト)での表示です.

          例)D0 = 000000007

メモリ中のデータの値は,16進数の2桁(つまり8ビット=1バイト)に区切られての表示です.

 

2.     ファイルの準備

今日の実習では、アセンブラの方法と、エミュレータの使い方について学びます。

まず、アセンブラソースプログラムファイルを用意します。次の命令をTerminal上で実行して下さい。

 


$ /u/matsuki/jishu3-setup ユーザ名 <Enterキー>

 

 

3.     擬似命令 equ

ここでは,擬似命令equについて学ぶ.サンプルプログラムsub2.semacsで開いて見てみましょう.

.org  0x0000

.dc.l 0x5000

.dc.l start

 

.org  0x0400

start:            

        .equ       X1, 15

        .equ       X2, 10

        .equ       X3, 30

        .equ       X4, 20

 

        move     #X1, %d0

        sub        #X2, %d0

        move     #X3, %d0

        sub        #X4, %d0

 

        .dc.w      0x4848  /* BSVC break 相当 */

        stop       #0          /* 終了 */

        .end

 

前回の実習に習って,このsub2.sをアセンブルし,BSVCのエミュレータを使って,実行しましょう.

 

擬似命令equは,指定された値をシンボル化するものである.例えば,上のプログラムでは,「.equ X1, 15」において,15(10進数)X1という名前でシンボル化している.この様子をBSVCの「Program Listing」で見てみよう(下図).そうすると,まず,気づくことは擬似命令の部分は,アセンブルしたコード(機械語)がないということである(下図@).これは,アセンブルした段階で,シンボル化した変数は,すべて対応する値で置換されるためである.そのため,「equ」に相当する機械語は表示されない(存在しない)のである.

400番地の命令は,「move #X1, %d0」であり,シンボル化したX1が使われている.それに対応する機械語では,「303C 000F」とある(下図A).前半の「303C」の意味は,「レジスタd0に,ソース・オペランドの値を転送(move)しなさい」というものである.そして,後半の意味はソース・オペランドに指定した値そのものであり,ここでは16進数で0F10進数で15)が指定されている.X1でシンボル化した15という値が,アセンブルした時点(機械語になった時点)で,機械語の命令に直接反映されていることが分かる.

A

 
テキスト ボックス: @ アセンブラ命令資料のp.266を参照

 

4.     エミュレータ(m68k-emu)の諸機能

(1)   レジスタへの値の設定

レジスタの値を設定する方法を説明する.ここでは,例としてレジスタD0の値を設定してみる.BSVCの画面(下図)の左側にあるレジスタの一覧から,設定したいレジスタ(ここではD0)をマウスでダブルクリックする(選択されると灰色になる).そうすると,画面の様にレジスタの値を設定するダイアログが開くので,そこに任意の値を入力し,「OK」のボタンをクリックする.その結果,レジスタの値が変更される.ここでは,レジスタD04016進数)を入力しておきましょう.

 

レジスタ一覧

 

 

 

(2)   プログラムカウンタに値を設定してのプログラム実行開始

この後の説明のために,「Reset」ボタンを1回クリックしておきましょう.

プログラムカウンタの値は,レジスタ一覧の中の下から2番目にある,「PC」と書かれた所にある.プログラムカウンタは,次に実行する命令が格納されている,アドレスを保持している.左下図の例においては,現在プログラムカウンタの値が「00000400」となっている(ここでは,400の上位の桁の0は無視して話を進める)ことから,次に実行されるのは,Program Listing中の青線が引かれている行「move #X1, %d0」である.ここで,プログラムカウンタを先のレジスタの値の設定を利用して,直接変更してみよう.レジスタ一覧の中にあるプログラムカウンタをダブルクリックし,その値を「40C」に変更する§(右下図).それにより,プログラムを強制的に40C番地から始めることが可能になる.ここで,注意することは,プログラムカウンタを直接変更しただけであり,400番地,404番地,406番地の命令は実行されずに飛ばされたということである.そのため,プログラム終了時の計算結果は(1)でレジスタD0に入力した値4016進数)からX4の値2010進数)を引いたものになっているはずである.計算どおりになったか確認せよ.

 

次に実行される命令(実際には青線で表示)

 

§レジスタ一覧には8桁の表記でPCの値が表示されているが,ダイアログで,値を入力するときは,40Cの上位の桁の0は省略して入力することが出来る.

 

課題1

  sub2.s を以下のように書き換えた(sub3.s).このsub3.sをステップ実行し,各sub命令実行直後のPC(プログラムカウンタ),データレジスタD0SR(ステータスレジスタ)の値を調べなさい.さらに,そのSRの値の意味について説明しなさい.

 

.org        0x0000

.dc.l       0x5000

.dc.l       start

 

.org        0x0400

.section .text

.even

start:    

.equ X1, 15

.equ X2, 10

.equ X3, 30

.equ X4, 20

 

move #X3, %d0

sub  #X3, %d0

move #X4, %d0

sub  #X1 %d0

move #X2, %d0

sub  #X3, %d0

 

              .dc.w      0x4848   /* BSVC break 相当 */

              stop       #0          /* 終了 */

              .end

 

 

5. 無条件分岐命令の振る舞い

ここでは,ステップ実行を用いて,無条件分岐命令を使ったときのプログラムの流れを確認する.特にプログラムカウンタPCの値の変化にも注意すること.

 


課題2

lenz.s についての問題.

(1)  bra SLEN_LP」の実行直後のプログラムカウンタの値を報告しなさい.

(2)  1行の命令を実行するのに1秒かかるとする.このとき,clr命令(プログラムスタート)からプログラムカウンタが000418になるまで(.dc.w 0x4848まで)に要する時間を求めよ.

  lenz.s は,「/u/matsuki/jishu3-setup ユーザ名 <Enterキー>」の実行によって作成されるファイルである.その中身は次の通り.

 

**

**      $00で終了するデータの長さを求めるプログラム

**

 

**

**      STRから始めて、$00が見つかるまで

**      1バイトずつカウントする

**      カウント結果はレジスタd0に格納する

**

 

.org    0x0000

.dc.l   0x5000

.dc.l   start

 

.org    0x0400

.section .text

.even

start:

        clr.l   %d0     /* カウンタ(d0)のクリア  */

        lea     STR, %a0

SLEN_LP:       

        move.b  (%a0)+, %d1

        cmpi.b  #0, %d1 /* d1??が等しければ、??へジャンプする  */

        beq     STR_END

        addq.l  #1, %d0 /* 1カウントアップする  */

        bra     SLEN_LP

 

STR_END:       

        ** 実行の終り

        .dc.w   0x4848  /* BSVC break 相当 */

        stop    #0      /* 終了 */

 

.section .data

.even

STR:    dc.b    'a','b','c','d','e',0

        .end

 

                      

6. cmp 命令と条件分岐でのステータスレジスタとプログラムカウンタの変化

 


課題3

lenz.s についての問題

(1)  cmpi.b #0, %d1」での処理内容について説明しなさい

(2)  (1)の実行直後のSRの値を調べなさい.また,その意味(なぜそうなったのか)を説明しなさい.

(3)  beq STR_END」の実行直後のプログラムカウンタの値を,ステップ実行によって観察し,結果を報告しなさい

 

今日の実習はここまでです。

 

参考Webページ: http://www.db.is.kyushu-u.ac.jp/kaneko/as/index.html