• 検索結果がありません。

H8のアセンブラ

ドキュメント内 PowerPoint プレゼンテーション (ページ 31-44)

実際にアセンブラを読んでみよう

– 方法はいくつかあるが、今回は最後に生成された実行 形式ファイルを逆アセンブルしたものを確認する

手順

– 先程、作成したフォルダ「4.1」をコピーして「4.2」

フォルダを作成

– lib.cファイルに関数を追記(P.155 リスト4.13)

– main.cに関数呼び出しを追記(P.155 リスト4.14)

– make を実行

– Cygwinで以下のコマンドを実行

$ /usr/local/h8300-elf/bin/objdump –d kzload.elf

逆アセンブルの結果

0000010c <_main>:

– main関数の先頭

000004f8 <_func>:

– func()関数の先頭

00000162 jsr @0x4f8:24

– func()の呼び出し箇所だろうと想像できる

ニーモニックの細かい文法は気にせず、想像で読 んでいくことがコツ

逆アセンブルの結果

0000015a: mov.w #0x2, r1

– r1レジスタに2を代入

0000015e: mov.w #0x1, r0

– r0レジスタに1を代入

H8はR0~R7という16ビットレジスタを8個持っ ている。拡張レジスタとしてE0~E7という16 ビットレジスタがあり、これらを組み合わせて ER0~ER7という32ビットレジスタとして利用 することができる(long型整数やポインタ)

main()関数部

79 01 00 02 mov.w #0x2, r1

– 「79」はオペコード、後ろ3バイトがオペランドで、

1バイト目は値の格納先レジスタ、後は代入値 – R1に0x0002という値を代入

ビッグ・エンディアンとリトル・エンディアン

– 「0x0002」を格納するとき、ビッグ・エンディアン

は「0x00」「0x02」、リトル・エンディアンは「0x02」、

「0x00」とひっくり返して格納する

– CPUによって異なり、H8はビッグ・エンディアン。

Pentium系CPUはリトル・エンディアン。近年の多く はビッグ・エンディアン。

main()関数部

イミディエイト値(即値)

– オペランドにレジスタに代入する「0x0002」という値 が、そのまま記述

– 命令内に直接記述される数値

func()関数部

mov.l er6, @-er7

– H8ではER7がスタック・ポインタとして利用される – スタック・ポインタを減算してスタック4バイト領域 を確保してスタック・ポインタの指す先にER6の値を 格納(ストア)する

– ER6が上書きされてしまうので、ER6の値(内容)を スタックに退避している

– スタックを獲得するのにER7の値を減算している。ア ドレス値が少なくなる方向に伸びること(下方伸長)

– 「@er7」レジスタの値をアドレス値として、アドレ スが指す先のメモリの意味(レジスタ間接)

→メモリ参照の方法をアドレッシング・モード

func()関数部

アドレッシング・モード

H8は8種類のアドレッシング・モードを持つ No 、 アドレッシングモード、 記号

(1) レジスタ直接 Rn

(2) レジスタ間接 @ERn

(3) ディスプレースメント付きレジスタ間接 @(d:16, ERn)/@

(d:24, ERn)

(4) ポストインクリメントレジスタ間接@ERn+

プリデクリメントレジスタ間接@-ERn

(5) 絶対アドレス @aa:8/@aa:16/@aa:24

(6) イミディエイト #xx:8/#xx:16/#xx:32

(7) プログラムカウンタ相対 @(d:8,PC) /@(d:16, PC)

(8) メモリ間接 @@aa:8

func()関数部

アドレッシング・モード

– 「@-er7」レジスタの加減算とメモリ・アクセスを1 命令で同時に行う

– スタック操作に2命令が利用されると、その命令の間 で割り込みが入りスタック操作された時に、スタック の整合性が取れなく可能性がある

– スタック操作は1命令で行える必要がある

func()関数部

mov.l er7,er6

– スタック・ポインタであるER7の値をER6にコピーし ている

– ER6はフレーム・ポインタと呼ばれる使われ方をして おり、スタック・フレームの先頭を指している

– ER6もER7も、ポインタとして利用されるため、アド レスを保持する必要があるので、32ビットレジスタ が利用される。

func()関数部

subs #4, er7

– スタック・ポインタであるER7をさらに4バイトだけ 減算して、4バイトの領域を確保

– func()の内部で利用している自然変数「c」の領域 – 「#4」の4は定数値を表すイミディエイト値(即値)

func()関数部

add.w r1,r0

– R0とR1の値を加算して、R0に代入 – 「a +b 」の処理(1 + 2)をしている

mov.w r0, @(0xfffe:16, er6)

– 加算結果はR0に格納されているが、自動変数「c」

はスタック上に存在

– フレーム・ポインタを減算してアドレスを計算して、

そこに加算結果を代入

func()関数部

mov.w @(0xfffe:16, er6), r0

– スタック上に格納されている変数「c」の値をr0に代 入することでモリチの準備をし、R0を関数の戻り値 とする

– 元々、R0に「c」の値が入っていたからムダな処理 – 「c」をvolatile定義したため、最適化処理が行われ

ていない

– 「加算して、結果をスタックに保存して、戻り値を準 備する」という一連の処理が最適化されていない

func()関数部

adds #4, er7

– スタック・ポインタを4バイト加算することで、自動 変数「c」の為に確保していたスタックを開放

mov.l @er7+, er6

– スタック上に対比されていたER6の値をER6に読み込 んで(ロード)、ER6を元に戻す

– ロード後にスタック・ポインタであるER7は4バイト 加算

rts

– スタック上から戻り先アドレスを取得し、ジャンプし て関数の呼び出し元に戻る

ドキュメント内 PowerPoint プレゼンテーション (ページ 31-44)

関連したドキュメント