はじめてのAVR
2002-02-24

AT90S2313のアセンブルプログラム開発。
限られたウェブ領域ではとても書籍にかないません。詳しくは市販の書籍を買って
勉強してください。CQハムラジオ2001年11号や2002年3号に初心者向けに基本から
解説した記事があり、とても役に立つと思います(2002/2月現在)。
  高級言語のCやBASICは使い慣れればそれなりに便利ですが結局1Kワード
のプログラム領域にコンパイラは重荷すぎて、あれもこれもはデバイス1個で
足りず、デバイスの限界の前にプログラム領域が尽きてしまいます。

	高級言語<簡単にプログラムが作れる> ⇔ <壁が高い>アセンブラ
デバイスの性能を引き出す前にコンパイラが限界 ⇔ 工夫次第でどこまでも

一度でも壁を越えたら、あとは楽勝! 

<特に断らなければ、次の事とします> 
CPU=AT90S2313 
言語=アセンブラ
開発機=MS-DOS 7(いわゆるWindows)マシン
 

§1 プログラム開発の流れ
1−1	回路作成
		・自作の経験と知識が必要です
		・アナログのみでなくデジタル(論理)回路の知識も必要です
	何を制御するのか、そのためにどんな部品が必要でどのような動作をさせるかなどを
	考え回路を描きます。
	回路はPCのソフトを使って描いても紙に手書きしても構いません。 

1−2	基板製作
		・自作(半田付け)の経験が必要です
	作ったプログラムが正常かどうか動作させて調べるために最初はジャノメ基板に
	回路図通りの配線をしてCPUを挿すだけの状態にしておきます。
 
1−3	プログラム作成
		・CPUの基礎、2進法、ブール代数の知識が必要です
		・発想力、空想力、遊び心が必要です
	PC付属の「NOTEPAD.EXE」を使ってプログラムを書きます。プログラムを考える
	時に一番必要なのは、CPUの命令セットを知る事(覚えなくて良い)です。
	つぎに重要なのは、各命令が実際にCPUで実行されたときに何が起こるかの
	理解です。
	この2点は、これまで何度もこのウェブページで説明してきました。

1−4	アセンブルと書き込み
		・アセンブラ・ソフトの操作知識が必要です
		・アセンブラ文法の知識が必要です、CPUの命令セットと一緒に勉強!
		・AVRライターソフトの操作知識が必要です
	プログラム言語が「C」でも「BASIC」でも「アセンブラ」でも使う言語の
	コンパイラ/アセンブラの操作を覚え使いこなさないといけません。
	Cの関数や取り決め事を理解するノーミソがあったら、アセンブラの使い方を
	覚えるなんて100倍簡単。

1−5	動作チェック
		・注意力が必要です
	プログラムを書き込んだCPUをジャノメ基板につけて、実際に動作させます。 
	最初から正常に動作するなんて、まずあり得ません。回路が間違ってるのか、
	プログラムが間違っているのか論理的に判断しますが、時には直感が解決の道を
	開くこともあります。

動作チェックでうまくいかなかったら1−3か1−1からやり直します。
これが大まかな流れです。 

 
§2 アセンブラの概要
2−1	アセンブラとは? 
	・Windows上で、あるいはMS-DOS上で走るアプリケーションソフト。 
	・文字や数字で書かれた自分のソースプログラム(テキストファイル)を16進の 
	  数字だけのテキストファイルに変換する変換ソフト。
	・ワンチップマイコン(CPU)を動作させるためのプログラム言語の1つです。

2−2	用語の意味
	ソースファイル:CPUを働かせる為のプログラム。 「MSワード」,「ワード
		パッド」や「ノートパッド」で書きます。書いたプログラムは名前を付けて
		DOSテキスト形式で保存します。ソースコード、ソースプログラム、
		原始プログラム、あるいは単にソースと呼ぶこともあります。
	アセンブル:ソースをアセンブラによって変換する作業のこと。変換が終了したら、
		オブジェクトができます⇒「オブジェクトが生成される」と言います。
	オブジェクト:ソースをアセンブルして生成されたファイルのこと。変換されて
		できたオブジェクトは、テキストファイル(ワープロソフトで読み、見る
		ことができる状態)ですが16進数の羅列です。
	リストファイル:アセンブルするとき、オブジェクトだけでなくこのファイルを
		自動的に作るアセンブラもあります。ソースに書かれた1つ1つの命令(行)
		に対応するオブジェクトコードがついた状態のテキストファイルです。
		リストファイルは、生成する・しないの指定ができます。
	コンパイラ:高級言語で書かれたプログラムのソースを、アセンブラのソースに
		変換する変換ソフト。 コンパイラに関連して「リンカ」などの用語が
		ありますが、アセンブラの事ではないので省略。
	コンパイル:高級言語のソースをアセンブラのソースに変換すること。コンパイルに
		よって生成されたアセンブラ・ソースは、再度アセンブラでアセンブルして
		オブジェクトを生成してはじめてCPUが実行できる(CPUに書き込める)
		状態になります。
	マシン語:オブジェクトファイルのような16進数(2進数)のファイル。
	ターゲット:生成されたオブジェクト(マシン語)が動作する環境あるいは、それを
		実行させるCPUのこと。

2−3	プログラム言語の種類
	プログラム言語は「高級言語」と「低級(原始)言語」、「マシン語(機械語)」が
	あります。CPUが実行できるのはマシン語だけです。
	低級言語であるアセンブラは、マシン語の命令と1対1に対応してちょっとだけ人間に
	分かり易い記述ができます。
	一方高級言語(Cなど)は人間がより簡単にプログラムを作るための便利な命令が
	ありますが、1つの命令は複数のアセンブラ(マシン語)命令からできています。
	そのためオブジェクト(マシン語)を得るために、アセンブラは1回、コンパイラは
	2回の変換(翻訳)が必要となります。
	8ビットCPUの黎明期はアセンブラすらなく(あっても環境が高価)、誰もが
	ハンドアセンブルといって、ノートに走り書きしたプログラム(ソース)を見ながら
	マシン語コード表と見合わせて16進数を書き並べ、それに従い8個のトグルスイッチ
	で1バイトずつ手作業でRAMにマシン語を書き込んで実行させていました。
高級言語を使うのは… 
	・Windows上で走るプログラム(ワープロ、画像処理、コンパイラやアセンブラ)。 
	・複数のプログラマーが手分けして作らないと手に負えない大規模プログラム(ゲーム)。 
	・アセンブラでプログラムを作るのに馴れていない場合。高級言語が最適・快速な 
	  ルーチンをひねり出します。 
	・プログラム開発の時間的余裕がない時。 
低級言語を使うのは… 
	・画像処理とか、大きなデータを扱わないプログラム。 
	・複雑でないプログラム(この表現はあまり正しくない)。
	・プログラム領域(パソコンでいうメモリー)が数キロバイトしかない場合や大きな 
	  領域を必要としないプログラム。
	・高級言語の限界を超えた高速処理、複雑な処理を限られたプログラム領域で
	  行う場合。

2−4	アセンブラでプログラムを作るために
	ターゲットCPUの命令以外に、アセンブラに指示を与える命令があります。
	「指示命令」あるいは「擬似命令」と呼びます。
	擬似命令はアセンブルしても何かのマシン語が生成されるわけではありません。
	アセンブラに対してCPUの種類を教えたり、プログラムを書きやすくするのが
	擬似命令です。
	また、プログラムを見易くするために注釈(コメント)を書く事もできます。
	つまり…
	ソースに書くのは「ターゲットCPUの命令」+「擬似(指示)命令」+「コメント」です。
	

§3 AT90S2313の命令と指示命令
・AT90S2313の構造(3−1)
・指示命令など(3−2)
・AT90S2313の即値命令(3−3)
・AT90S2313のインダイレクト命令(3−4)
・AT90S2313のダイレクト命令(3−5)
・AT90S2313のレジスタ処理命令(3−6)
・AT90S2313のCPU制御命令(3−7)
・AT90S2313のビット命令(3−8)
・AT90S2313のポート制御命令(3−9)

3−1	AT90S2313の構造
	プログラム領域
	$0000〜$03FF	自分のプログラムを置く領域です。
			1キロワード、1024ステップ。これは16F84と同じ
			プログラムステップ数です。
			中身は2キロバイト分ありますが1つの命令は2バイトで
			CPUは1つの命令を2バイトずつ取り出して実行します。

			LPM命令=Load Program Memoryでは注意が必要です。
			その項目を見てください。

			2キロバイトを超えるデバイスもありますが、便利(当然)
			なのはリニア構造なので1024ステップ毎の区切りが無く
			PICのようにバンク切り替えすることなくどのアドレスへも
			ジャンプ/アクセスできます。

	データ領域(3つに分けて説明します)
	$00〜$1F	汎用レジスタ領域です。レジスタは変数や計算結果を入れるウツワ
			です。r0からr31までの32本あります。
			r16からr31の16本は全て、16F84のWレジスタと同じ
			使い方ができます。r0からr15は即値の命令が使えない
			事を除けば後半16本のレジスタと同じです。
			命令によっては、特殊な用途に決められているレジスタが
			あります。
			r0,Z:LPM命令のインデックスがZ、結果がr0。
			インデックスレジスタとして、以下の2つのレジスタペア:
			X=r27(XH)とr26(XL)
			Y=r29(YH)とr28(YL)
			Z=r31(ZH)とr30(ZL)

	$20〜$5F	IOレジスタ領域です。
			実際のアドレスは$20〜$5Fですが、このアドレスは使いません。
			$00〜$3Fにマップされています。
			実際のアドレスで使うのは間接アドレッシングによるアクセス
			だけで普段は、そのような使い方しません。
			ここは、PICでいうシステムファイルに相当し、ポートの
			設定、ステータスレジスタ(フラグ)などがあります。


	$60〜$DF	いわゆるデータSRAM領域で、128バイトあります。
			PICのレジスタはSRAMに割り当ててありますが、AVRのSRAMは
			レジスタとは別に純粋にデータ領域として使えます。
			サブルーチンコールや割り込みを使う場合はスタックポインタを
			この領域にセットする必要があります。
			通常SPLはSRAM領域の末尾に設定します。
スタック:	SRAM領域と共用される領域です。SPLレジスタ(スタックポインタ)に
		よってSRAM領域中で使われる番地が指定されます。
		rcallなどサブルーチンコール命令は、サブルーチンの実行が終了したら
		コール命令の次の命令に戻って実行を続けますが、このときコール命令は
		サブルーチンに分岐する前に、戻るべき命令の番地(アドレス)を
		スタックに一時保管します。 rcall命令=push命令+rjmp命令
		また、サブルーチンの中で別のサブルーチンコールがあると、先に
		スタックされた上に次の戻り番地を積み上げます。
		スタックは1回積まれるとSPLが自動的にアドレスの若い方へ変化します。
		スタックは「先入れ先出し」方式で、積まれたデータを取り出すと、
		SPLが自動的にアドレスの大きい方へ変化します。
		push命令ではコール命令の時と同様にスタックにレジスタの値を
		積み(積む=コピーするだけで分岐はしない)SPLが−1され、pop命令は
		コール命令やpush命令によって積まれた値をスタックの一番上(最新の
		もの)からレジスタに取り出し(コピー)、SPLが+1されます。

3−2	アセンブラ指示命令など
	アセンブラでプログラムを書くときの決まり。
		・1行に1つの命令を書く。1行に2つ以上の命令は書けない。
		・1つの行に1つ指示命令を書くことができる。
		・行の中に ;を付けると、それ以降はアセンブルされない。
		・先頭に ;を付けた行はコメント行。
		・指示命令は行の先頭から書き始める。
		・命令は行の最初に1つ以上の空白またはタブを空けて書く。
		・ラベルは行の先頭から書き始め、ラベル名の最後に:を付ける。
		・ラベルに続けて命令を書く場合は、1つ以上の空白かタブを空ける。
	以下、指示(擬似)命令を説明します。実際のソースプログラムを見ながらの方が
	分かりやすいと思います。

	ORG指示命令:アセンブラはCPUが命令を実行するときのように、プログラムカウンタ
		(アドレスカウンタ)を持っています。 ORGはそのカウンタの値を与える命令です。
		ソースに書かれた1つの命令をアセンブルしたら、そのカウンタを+1します。
		実際のCPU内部ではプログラムカウンタの数え方がバイト単位のため+2します。
		ただしSTS命令など4バイト命令はプログラムカウンタが通常の2倍進みます。
		アセンブラがアセンブル中にラベルを見つけたら、そのラベル(文字列)に現在の
		カウンタの値を与えます。
		どこかでそのラベルへのジャンプ命令やコール命令があったら、ラベルに与えた
		カウンタの値からジャンプやコールの飛び先を計算してマシンコードを生成します。
		これを「ラベル(プログラムカウンタ)の参照」と言います。
	.org (式)	(式)は$000〜$3FFの範囲の数値です。定義済みのラベル
			や演算子を使って書くこともできますが、その必要がある
			ようなプログラムを作ったことが無いので説明できません。
	.org $000	アセンブラのアドレスカウンタがゼロになります。 この次の
			行に現れた命令は、AVRライターでターゲットのゼロ番地
			に書き込まれます。
	.org $60	アセンブラのアドレスカウンタが$60になります。データ
			SRAM領域はこの番地から始まりますので、ラベルを使って
			この領域を参照させる場合に使います。ただし、アセンブラは
			どこがデータ領域のラベルかを感知しませんから、この指示
			命令に先立ってdseg指示命令を書いておく必要があります。

	CSEG、DSEG、ESEG指示命令:
		最初のはプログラム書き始めることを宣言します。次のがデータを書き
		始めることを宣言します。最後のが内臓EEPROMのデータを書き始め
		ることを宣言します。 おそらく、この宣言をした直後はORG指示命令で
		アドレスカウンタを指定しなくても、$000や$60に自動設定されるはずです。
		また、CSEG $10 のようにORGを使わない書き方もできると思います。
	.cseg (式)	(式)はプログラム領域として矛盾のない値を書きます。(式)は
			省略できます。

	.cseg $000	普通、こう書くのでしょう(?よく分かりません)。

	.dseg		この次の行からデータを配置することができます。

	.eseg		この次の行からEEPROMのデータを配置することができます。

	レジスタ定義擬似命令DEF:
		プログラムを書くときにレジスタ名(r0〜r31)をそのまま書く以外に
		あらかじめ名前を付けて、その名前を書くことができます。
	.def W=r16	r16と書くべきレジスタをWと書くこともできます。

	ラベル定義擬似命令EQU:
		ラベルには2種類あります。
	     (1)オペランドの値を数値で書く代わりにあらかじめ名前を付けて、その
		名前を書くことができます。
	.equ abc=5	あらかじめabc=5と定義しておけば、5と書く代わりにabcと
			書くことができます。
	 ldi W,abc	この命令は、上記の定義をしておけば ldi r16,5 と同じ事です。

	     (2)プログラム中につけたラベルは自動的にロケーションカウンタの値を持ち
		アドレスの代わりに参照されます。 分岐やサブルーチンコール命令では
		数値を書かずに、ラベル名を書きます。
	tasu: add W,r10	ラベル名tasuにはこの命令が置かれた場所のロケーションカウンタの
		値が自動的に与えられます。与えられた値はラベル名が参照される時に使われ
		ます。
	 rjmp tasu	このような分岐命令においてtasuが参照されます。アセンブラは
		自動的に計算されたtasuの値を使ってこの命令をオブジェクトに変換します。
		だからプログラマーはtasuの番地を知る必要はありません。

3−3	AT90S2313のイミディエート命令
	イミディエートとはPIC的に言うとリテラルワードです。普通データはSRAMに存在
	しますが、この命令は演算する値が命令(プログラム領域)の中に埋め込まれています。
	CPUが命令を取り出した時点で演算の対象もCPUの手元にあり、即演算に取りかかる
	ことのできる命令です。イミディエート(即値)命令で使うことのできるレジスタは…
		r16〜r31
	です、命令の動作は命令表を見てください。

	イミディエート命令は、次のような"I"のつく命令です。
		LDI、SUBI、ANDI、ORI、CPI、ADIW、SBIW、SBR、CBR
	ADDI命令がありませんので即値の加算はマイナス符号を付けて、SUBI命令を使います。
		subi	W,-$10
	これは addi  W,$10 の動作をします。オペランドは符号付き1バイト値(-128〜0〜+127)で
	あることに注意してください。
	SBRやCBRはオペランドの書き方が良く分らないので、わたしは使った事がありません。
	マシンコードはANDIやORIと同じものが生成されるのではないかと思います。
 
	プログラムカウンタに対する符号付きイミディエート値の加算は「CPU制御命令」に
	まとめています。

3−4 	AT90S2313のインダイレクト命令
	インダイレクトとは対象となるデータのアドレスをレジスタで示す事です。
	データのアドレスを示すためのレジスタは2つのレジスタペア、
	X=r27(XH)とr26(XL),Y=r29(YH)とr28(YL),Z=r31(ZH)とr30(ZL) を使います。

	インダイレクト命令は次のものです。
		LD、ST、LDD、STD
	この命令のレジスタペアが示すのはデータ領域(3−1参照)のアドレスです。

	インダイレクト命令で、プログラム領域(3−1参照)からロードする命令もあります。
	(プログラム領域に書き込む命令はAT90Sシリーズでは使えません)
		LPM
	Zは取り出すデータの置かれた番地を1バイト区切りでアクセスするので、下のような置数データを
	取り出すには、
		ldi	ZL,low(data1+data1)
		ldi	ZH,high(data1+data1)
	このようにラベル名の2倍をZにセットしておき(ORG指示命令を参照)、LPM命令で
	取り出すことができます。
	LPM命令によって得られた1バイトは常にr0に返ります。書き変える事のない固定データで、
	繰り返し使うものは、余裕があればプログラム領域に置いた方が取り扱いが容易です。

	プログラム領域に置数する場合、次のように記述します。
		data1:
		.db	$10,200,0b01001111
		.dw	32769,$F417
		.db	"Press OK"
	バイト置数でデータのバイト数が奇数個の場合アセンブラは$00を追加して偶数個にします。

	★バイト置数命令の記述上の注意★
	上のバイト置数のように
		.db	$10,200,0b01001111
	と記述したソースのアセンブル結果は、このように(意図した通りに)1バイトずつの
	データが生成されます。
		10,C8,4F,00	(最後の00はデータが奇数個のために生成される)
	 しかし、このように
		.db	$10
		.db	200
		.db	0b01001111
	1バイトずつ単独で記述すると、アセンブル結果は、
		0010,00C8,004F	つまり、バイト単位に区切ると00,10,00,C8,00,4F
	と、なぜか 上位バイトが$00のワードデータが生成されてしまいます。(2003/2/16追加)

	8ビットレジスタを使うインダイレクト命令があります。
		PUSH、POP
	この2つの命令はSPL(AT90S2313では8ビット)が示すデータ領域(3−1参照)からレジスタの
	データをロードしたりストアできる、SRAM上のデータに対する最も手軽なアクセス手段です。
	主に割り込みプログラム内で使います。レジスタが足りないときも役に立ちます。
	目的があってSPLの値を書き換える場合でも、とても注意してください。

	プログラムカウンタに対するインダレクトは「CPU制御命令」にまとめています。

3−5	AT90S2313のダイレクト命令
	ダイレクトとは直接という意味で何が直接かというと、対象となるデータのアドレスを
	イミディエートで示す事です。わたし的には「ストレート」ですね,命令の中に即値が
	埋め込まれているけど、そのイミディエートはデータSRAMのアドレスを示すものだから
	インダイレクト?みたいに混乱します。 この命令がロード/ストアする対象はもちろん
	データ領域(3−1参照)です。
	
	ダイレクト命令はストレートの"S"が付く次の2つで、rはr0〜r31、Kは2バイトの即値です。
	ATMELの原文や和訳の命令表に付いている小文字のkは誤りです大文字のKに訂正して
	おきましょう。 この命令は4バイト命令です。
		LDS r,K、STS K,r

	データSRAM上に置かれたデータを連続して扱うのでなければ、インダイレクトのロード/
	ストア命令やPUSH/POP命令と同じ2クロックサイクルだから便利です。

3−6 	AT90S2313のレジスタ処理命令
	レジスタ処理命令は3−3から3−5に含まれない、レジスタだけの命令です。
		MOV、ADD、ADC、SUB、SBC、AND、OR、EOR、COM、NEG、INC、DEC、TST、CLR、SER、
		CP、CPC、LSL、LSR、ROL、ROR、ASR、SWAP
	これらの命令に限りませんが、命令実行後フラグが変化するものがあります。
	どの命令で、どんな場合、どのフラグが、どう変化するかを知ることが重要です。

	MOV命令はレジスタのコピーですから、元のレジスタの値は命令実行後も変わりません。

3−7	AT90S2313のCPU制御命令
	わたしの説明には、分岐命令やコール命令の項目がありません。
	分岐命令はプログラムカウンタ(PC)に対する演算やデータ移動だからです。
	PCに対する演算でPCの値を変更することはつまり、プログラムの流れを変える、
	CPU制御にほかなりません。

	CPU制御(分岐)命令には条件付と条件なしがあります。
		RCALL, RJMP, BRxxの条件ブランチ
	アセンブラが自動的にオペランドに書かれたラベルの値と現在のロケーションカウンタの差を
	計算します。これまでのイミディエート、インダイレクト、ダイレクトのような分け方を
	するなら、Rの付くCPU制御命令はリラティブ(相対)と言います。
	例えばrcall命令のマシンコードは $dxxx です。xxxの12ビット分が符号付の値で、
	実行されるときはPCとxxxが符号付で加算されますから、相対アドレスは1Kワードの
	プログラム領域のどこでもバンク切り替えなしに分岐できます。ただし、BRxx命令は
	相対値が7ビットですからアセンブル中、それを越えたラベル(オペランド)値があったら
	アセンブラは「相対範囲超過エラー」を出します。
	rcall命令はスタックに現在のプログラムカウンタ値+2(+1ではないのは1つの命令が
	2バイトだから)をpushし下で説明するret命令で、そのアドレスをスタックからPCに
	popしてコピーします。常に、このことを意識してプログラムを作れば新しいアイディアが
	浮かぶかもしれません。
	普通は意味の無い事ですが、push命令とrjmp命令の2つを使ってrcall命令の動作をさせる
	事ができます。

	1つ先の命令を飛び越すCPU制御命令。
		CPSE, SBxxの条件スキップ
	これらの命令は相対と言えますが、相対値が固定です。

	スタックポインタ(SPL)からインダイレクトでプログラムカウンタにコピーするCPU制御命令。
		RET, RETI
	スタックポインタが示す位置から16ビット値(2バイト)をPCにコピーし、スタック
	ポインタを−2します。
	この命令もPCを変更しますから分岐命令です。普通この命令はrcallやicall命令と入れ子
	にして使います。
	RETIは更に割り込みフラグをセットし、割り込みが許可されます。

	命令が無いのにPCが(勝手に)変更される場合。
		割り込み
	割り込みは、その要因によりCPUが自動的にコール命令と同じ動作をします。
	割り込みが起こる要因はCPUのポートの状態が原因となるものが2つ、CPUの
	内部状態が原因となるものが8つあります。
	割り込み要因はプログラムによって発生させるようにしてはじめて起こります。
	割り込み要因が発生しても、割り込みを許可しないとPCは変化しません。
	10ある割り込み要因は個別に発生される/させない、許可する/しない,を
	設定することができます。 わたしは割り込みを使ったことがありません。そのうち
	周波数カウンタを作ろうかと思っているので、そのときにレポートします。

	CPU外部からの割り込み要因。
		INT0, INT1
	これらはポートPD2(INT0)やPD3(INT1)の状態変化が要因となるもので、ポートを入力に設定
	していなくても有効です。 PD2やPD3の端子がlow→highの遷移を要因とするかhigh→lowを
	要因とするかまたはlowレベル状態を要因とするかを設定しておくと、その要因が発生したら
	CPUは実行中のプログラムを中断しスタックに再開するプログラムの番地をpushします。
	その後PD2なら$001番地の、PD3なら$002番地の命令を実行します。
	CPUが勝手に行うのはここまでですから、続きはプログラマーがプログラムしておく必要が
	あります。
		続きは…例えばint0の場合。
	$001にはint0の要因を処理するプログラム(ラベル)に分岐するrjmp命令を置きます。
	CPUがこのrjmp命令を実行し始めるときは割り込みが禁止になります。
	rjmpの分岐先には、まず保存しておかなければならないレジスタをスタックに退避します。
	それからこの割り込みに対応した処理をプログラムします。
	最後にスタックからレジスタを復帰します。
	元のプログラムに戻すためにはretかretiを使います。retiはリターンしてから、割り込みを
	許可にします。

	CPU内部で発生する割り込み要因。
		CAPT1 ,COMP1, OVF1, OVF0, UART RX, UART UDRE, UART TX, ANA COMP
	これらはCPU内部の状態が原因となるもので、どれもINT同様にrjmp命令を置いて割り込み
	処理プログラムに分岐させ、retかretiで元のプログラムに戻ります。

	割り込みを制御する命令
		CLI, SEI
	SEIはすべての割り込みを許可します。CLIはすべての割り込みを禁止します。 また、
	割り込みIOレジスタを制御する事で、個別の割り込みを禁止許可することができます。

	プログラムカウンタにペアレジスタの値をコピーする命令。
		ICALL, IJMP
	ATMELの説明では、この命令は「インダイレクト」となっていますがダイレクト命令あるいは
	MOV同様レジスタ命令と言えます,命令表の「動作」欄は PC←(Z) ではなく PC←Z となって
	いるでしょ?MOV命令もそうですよね(まあ見解の相違です)。
	相対のcallやjmp命令と同じ動作ですが、PCの16ビットをZレジスタの値で総変えします。
	1Kワードのデバイスでは、あえてこの命令を使う必要はありませんが、もし使うとすれば
	ZHを固定してZLに変数として(演算して)、この命令で飛び先を散らすテーブル処理が考えられ
	ます。

	何もしない命令
		NOP
	1マシンサイクル経過後、次の命令を実行します。1マシンサイクルはクロック10MHzで
	100ナノ秒。 何もしないけど時間が過ぎます。

 	SLEEP命令とWDR命令は使ったことがありません。

3−8	AT90S2313のビット命令
	この命令は、レジスタのビットをセットしたりクリアしたりする命令です。 ビット操作の
	対象となるレジスタは3−1,データ領域で説明した汎用レジスタとIOレジスタ領域で、
	どちらの領域かで命令のニモニック自体が違います。

	ビット命令には次のものがあります。
		SBI, CBI, BSET, BCLR, BST, BLD, SExとCLxのフラグビット命令
	BSETとBCLRはSBR/CBR同様オペランドの書き方が分りませんので使ったことがありません、
	1つ1つのフラグのセット/クリア命令がありますから、フラグレジスタに対するANDI, ORIの
	動作をするのでしょう。
	BLD/BSTは本物の(?)ユーザーフラグでプログラムステップ数の節約に使え、自分では多用
	しました。

3−9	AT90S2313のポート命令
	この命令はレジスタ命令/ビット命令の中で、処理の対象がポートレジスタです。

	ポート命令には次のものがあります。
		SBI, CBI, SBIC, SBIS, IN, OUT
	INとOUT以外は、はじめてではありません。 IN, OUTは汎用レジスタとポートレジスタの
	データコピー命令です。

	ポートBを全部出力にするには、次のように書きます。
		ser	r0
		out	DDRB,r0
		clr	r0
		out	PORTB,r0
	出力に設定したPORTBにビット毎、あるいはすべてのビットをいっぺんに出力することで
	そのピンが5V(当該ビットを1にしたとき)か0V(当該ビットを0にしたとき)になります。

	ポートDを全部入力にするには、次のように書きます。
		clr	r0
		out	DDRD,r0
	さらに入力ポートDの内部プルアップを有効にするには、入力に設定した
	このポートに1を出力します。
		ser	r0
		out	PORTD,r0
	内部プルアップはインピーダンスが高すぎてメカニカルなスイッチの入力に使うには
	チャタリングが収まるまでに時間がかかりすぎます,CPU外部に別途4.7KΩでプルアップ
	した方がいいです。TTLでドライブするなら内部プルアップだけを使います。
	入力に設定したポートDを読み出すにはPORTDではなくPINDを使います。
	

§4 AT90S2313の実践プログラム
	ここでは1つの処理をするプログラム,ルーチン/プロシジャを例にあげて、解説します。
解説しません。⇒別のページを探してください。

<コーヒーブレーク>
割り込みは初心者は使うなとか3−4最後のSPLの変更をしてはいけないとは申しません。
どんどんやって使いこなしましょう。
あなたのパソコンにたまに起こる青画面に「例外…0F2E0A9:0007B13」とか表示される訳の
分らないものは、実行していたアプリケーションプログラムが要因で割り込み掛かった状態で、
表示された16進数値は割り込まれた時のプログラムカウンタの「セグメント:オフセット」値です。
コンパイラ作られたアプリケーションは山のようにオープンしているパソコン上のプログラムの1つに
過ぎず、プログラマーは自分のプログラム以外の事を気にせずプログラムを作ったのが原因で
踏み込んではいけない場所に足を踏み入れ、ドツボにはまって割り込まれてしまいます。
ペンティアムx86(インテル系)CPUでは「割り込み」の事を「例外」と呼びます。