課題

FF200から機械語プログラムを置きなさい。
FF800番地 - FF801番地に2バイトの値が,FF802番地 - FF803番地に2バイトの値があり,
それぞれ正の整数であるとして,この2数の積を求め,FF804番地 - FF805番地に保存するプログラム。

●元にすべきプログラムは次のものである。

Cプログラムファイル mult.c
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;
}

x00とx01をかけてy0に答えをしまうプログラムなので,これを題意に合うように変更する方針をとる。

上記のmult.cをCプログラムをアセンブリプログラムに変換するプログラムc2asm.cmdでアセンブリプログラムに変換する。

●mult.srcとmult_1.srcが生成されるが,mult_1.srcが余計なコメント行を消したものである。

アセンブリプログラム mult_1.src
          .CPU        300HA
          .EXPORT     _x00
          .EXPORT     _x10
          .EXPORT     _y0
          .EXPORT     _main
          .SECTION    P,CODE,ALIGN=2

_main:                           ; function: main
          MOV.W       @_x00:24,E0
          MOV.W       @_x10:24,R0
          SUB.W       R1,R1
L10:                             
          BTST.B      #0,R0L
          BEQ         L11:8
          ADD.W       E0,R1
L11:                             
          SHLL.W      E0
          SHAR.W      R0
          BNE         L10:8
          MOV.W       R1,@_y0:24


          RTS


          .SECTION    D,DATA,ALIGN=2

_x00:                            ; static: x00
          .DATA.W     H'0055
_x10:                            ; static: x10
          .DATA.W     H'000A

          .SECTION    B,DATA,ALIGN=2

_y0:                             ; static: y0
          .RES.W      1

          .END

mult_1.srcで先頭のファイルの名前は不要,.EXPORTの行も(EXPORT:他のプログラムとあわせる際にこの名前が使えるように外部に見せますという意味)不要。
これらを削って,「アセンブリプログラム mult_1.src その2」を得る。

アセンブリプログラム mult_1.src その2
          .CPU        300HA

          .SECTION    P,CODE,ALIGN=2


_main:                           ; function: main

          MOV.W       @_x00:24,E0
          MOV.W       @_x10:24,R0
          SUB.W       R1,R1
L10:                             
          BTST.B      #0,R0L
          BEQ         L11:8
          ADD.W       E0,R1
L11:                             
          SHLL.W      E0
          SHAR.W      R0
          BNE         L10:8
          MOV.W       R1,@_y0:24


          RTS


          .SECTION    D,DATA,ALIGN=2

_x00:                            ; static: x00
          .DATA.W     H'0055
_x10:                            ; static: x10
          .DATA.W     H'000A

          .SECTION    B,DATA,ALIGN=2

_y0:                             ; static: y0
          .RES.W      1

          .END

行の左端にある「名前」+「:」はラベルであり,その次の行にあるプログラムやデータの存在アドレスを意味する。
実行プログラムの終端は「RTS(ReTurn from Subroutine)」になっている。Cプログラムではmain()が関数であるので,関数の終端としてこのようになっている。


●ここで以前作成した足し算プログラムを参考に仕上げていく。

2.(1)で使用した足し算プログラム 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


●「2.(1)で使用した test.src」において次のことが確認できる。
0FF130はプログラムの先頭アドレス

・プログラム本体は次の通り

    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へ

・プログラムの終了のところはいろいろな書き方があるが,つぎの2行が終了部
 (自分自身へのジャンプ)

EternalLoop:
    BRA EternalLoop ;永久ループ

・プログラム中の@data1,@data2,@data3はその変数のアドレスを表していた。
・つぎの表現は,アドレス0FF800からdata1,data2,data3を2バイトずつ並べているという意味であった。

    .SECTION D,DATA,LOCATE=H'0FF800
data1:
    .DATA.W H'1234
data2:
    .DATA.W H'2345
data3:
    .DATA.W H'3456


●「2.(1)で使用した test.src」が機械語に変換されたものは「2.(4)」に載っていた。

2.(4) 機械語に変換された状態
  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

FF130からプログラムが始まっていることがわかる。
@data1がFF800,@data2がFF802,@data3がFF804に変換されていることがわかる。



●「mult_1.src その2」に必要なものを書き加え,修正していく。
SECTION疑似命令のところに「LOCATE=」で,プログラムや変数のアドレスを設定することが出来る。
この課題ではプログラムの先頭がFF200なので修正,乗算の2変数はFF800,FF802に並んでいるので,先頭をFF800に設定する。
積を保存するところはFF804なので,これもFF804に設定する。

アセンブリプログラム mult_1.src その3
    .CPU 300HA
    .SECTION A,DATA,LOCATE=H'0FF030
    .DATA.L H'0FF200  ;リセットベクトル

    .SECTION P,CODE,LOCATE=H'0FF200
    MOV.L  #H'FFF00,ER7  ;スタックポインタ設定
_main:                           ; function: main
    MOV.W       @_x00:24,E0
    MOV.W       @_x10:24,R0
    SUB.W       R1,R1
L10:                             
    BTST.B      #0,R0L
    BEQ         L11:8
    ADD.W       E0,R1
L11:                             
    SHLL.W      E0
    SHAR.W      R0
    BNE         L10:8
    MOV.W       R1,@_y0:24
EternalLoop:
    BRA EternalLoop ;永久ループ

    .SECTION D,DATA
,LOCATE=H'0FF800
_x00:                            ; static: x00
    .DATA.W     H'0055
_x10:                            ; static: x10
    .DATA.W     H'000A

    .SECTION B,DATA
,LOCATE=H'0FF804
_y0:                             ; static: y0
    .RES.W      1
    .END


「MOV.W       @_x00:24,E0」の@_x00などのところは,直接アドレスを書いても良いが,上記のプログラムの方が,汎用性が保てる。

直接アドレスを書くとプログラムは短くなって次のようになるが,汎用性は失われた。

アセンブリプログラム mult_1.src その4
    .CPU 300HA
    .SECTION A,DATA,LOCATE=H'0FF030
    .DATA.L H'0FF200  ;リセットベクトル

    .SECTION P,CODE,LOCATE=H'0FF200
    MOV.L  #H'FFF00,ER7  ;スタックポインタ設定
_main:                           ; function: main
    MOV.W       @H'FF800
:24,E0
    MOV.W       @H'FF802:24,R0
    SUB.W       R1,R1
L10:                             
    BTST.B      #0,R0L
    BEQ         L11:8
    ADD.W       E0,R1
L11:                             
    SHLL.W      E0
    SHAR.W      R0
    BNE         L10:8
    MOV.W       R1,@H'FF804:24
EternalLoop:
    BRA EternalLoop ;永久ループ

    .END