このドキュメントは http://edu.net.c.dendai.ac.jp/ 上で公開されています。
アセンブリ言語はテキストファイルに記述します。 アセンブラのユーザーズマニュアル AVR Assembler Assembler source に示されているように記述します。 「ラベル: ニモニック オペランド」 を空白で区切って記述します。 ラベルの前に空白があってはいけません。 また、セミコロン(;)の後ろはコメントとしてアセンブル時に無視されます。 ニモニックの位置には他にディレクティヴ、マクロなどを置くことができます。
ラベル ニモニック オペランド コメント
.org 0x0013
reset:
ldi r16,low(RAMEND)
out SPL,r16
アセンブリ言語中で定数の演算式を書くことが出来ます。 アセンブラのユーザーズガイドの AVR Assembler Expressions にあるように C 言語で許されて いるような演算子がそのまま使えます。 但し、レジスタの内容は演算の対象ではありません。
アセンブラとはニモニックとオペランドから機械語を生成するものですが、 利便性を向上するためのアセンブラの機能があります。 ディレクティヴとはアセンブラに対する指示をする命令です。 ディレクティヴはピリオド(.)で始めます。
良く使うディレクティヴを紹介します。
マクロを定義します。 macro のオペランドにマクロ名を指定します。 マクロ定義の中で引数として @0 から @9 の 10 個の仮引数が使えます。 なお、AVR のアセンブラのマクロ中のラベルはローカルにしか使用できません ので、マクロ中に定義したラベルに外部からアクセスすることはできません。 なお、グローバルなラベルを使用するには #define 疑似命令を使用する手が ありますが、こちらこちらで基本的に一行で記述しなければならず、複数行を 書くには(\)を使用した継続行を使用する必要があります。
EQU などで使用できる関数を下記に示します。 なお、これらは一部なので、詳しくは アセンブラマニュアル Expressions を参照してください。
さて、この節では実際にプログラムを作成する手順を説明します。
アセンブルしたプログラムはシミュレータで動作を観察できます。 「プロジェクト→ プロジェクト名 のプロパティ」を選ぶと 設定画面が出ます。 Tool の設定画面で、 Simulator を選ぶと ソフトウェアシミュレータ を使えるようになります。 シミュレータはプログラムを一命令ずつ動かしたり、指定した所まで動かして 止めたり出来ます。
シミュレータはテープレコーダのボタンのようなボタンで操作をします。 なお、 右側の画面でマイコンの状態を見ることができます。
プログラムリストの行をダブルクリックすると左側に赤い丸が付きます。 これを ブレークポイントと言います。 矢印一つの Run ボタンを押すと、ブレークポイントで停止します。 これにより、プログラムの途中のレジスタの値などをチェックできます。
その他、一命令だけ実行する Step Into, Call 命令に関しては戻って来るま で一括で実行する Step over, サブルーチン中から抜け出すまで実行する Step out があります。
なお、実行中にI/Oのボタンを押すと、その値に変化させることができます。
以下のプログラムを program.bat というテキストファイルに収めます。
SET dude="C:\Program Files (x86)\Arduino\hardware\tools\avr\bin\avrdude.exe"
set conf="C:\Program Files (x86)\Arduino\hardware\tools\avr\etc\avrdude.conf"
rem %dude% -C %conf% -p atmega328p -cstk500v1 -P %1 -b 57600 -D -U flash:w:%2%:i
%dude% -C %conf% -p m328p -c arduino -P %1 -D -U flash:w:"%2":i
サンプルプログラムflashuno.asm の各ディレクティヴがどのような意味か、全て調べなさい。
サンプルプログラムflashuno.asm を機能毎に区分し、各機能を説明しなさい。
サンプルプログラムswitchtraining.asm を動作させなさい。
また、プログラムを読み、どのような動きをするのか、説明しなさい。
サンプルプログラムswitchtraining.asm の各ディレクティヴがどのような意味か、全て調べなさい。
サンプルプログラムswitchtraining.asm を機能毎に区分し、各機能を説明しなさい。
.cseg
.org 0x0000
rjmp reset
.org INT_VECTORS_SIZE
reset:
ldi r16,high(RAMEND)
out SPH,r16
ldi r16,low(RAMEND)
out SPL,r16
sbi ddrb,pb5
cbi ddrd,pd4
sbi portd,pd4
main:
sbi portb,pb5
sbis pind,pd4
rjmp onl
rcall shortwait
rjmp off
onl:
rcall longwait
off:
cbi portb,pb5
sbic pind,pd4
rjmp offl
rcall shortwait
rjmp main
offl:
rcall longwait
rjmp main
.equ shorttime = 4
.equ longtime = 40
.def wreg0 = r20
.def wreg1 = r21
.def wreg2 = r22
shortwait:
ldi wreg0,shorttime
rjmp wait0
longwait:
ldi wreg0,longtime
wait0:
ldi wreg1,0
wait1:
ldi wreg2,0
wait2:
nop
dec wreg2
brne wait2
dec wreg1
brne wait1
dec wreg0
brne wait0
ret
.exit
次の操作をする命令の組を書きなさい
flashuno.asm のプログラムを改造して、点滅の速さが2倍になるようにしよ う
flashuno.asm のプログラムを改造して、点滅の速さが1/2倍になるようにし よう
r16に入れた数だけ、0.1秒ずつLEDを点滅した後、1秒消灯する nblink というサブルーチンを作りなさい。 さらに、 次のプログラムと結合して正常に動作することを確かめなさい。
.cseg
.org 0x0000
rjmp reset
.org INT_VECTORS_SIZE
reset:
ldi r16,high(RAMEND)
out SPH,r16
ldi r16,low(RAMEND)
out SPL,r16
sbi ddrb,pb5
main:
ldi r16,0
loop:
inc r16
push r16
rcall nblink
pop r16
cpi r16,4
brne loop
rjmp main
番兵が0の数列をdbで確保し、各数列の値でblink()メソッドを呼ぶプログラム を書きなさい。
sample:
.db 3,3,7,0
.equ sampleadr = sample<<1
4番とGNDをつないだときだけ、LED が点灯するプログラムを作りなさい。
4番とGNDをつないだときは、1秒おきに2回LEDが点滅、つないでない時は 1秒おきに短くLEDが点滅するプログラムを作りなさい。
4番とGNDをつないだときは、1秒おきにLEDが1回点滅、2回点滅、3回点滅、 1回点滅,2回点滅、3回点滅と繰り返すが、 つないでない時は同じ回数の点滅を繰り返すプログラムを作りなさい。 つまり、3回点滅の時に線を外せば、そのまま3回点滅を繰り返し、 1回点滅の時に線を外すと1回点滅を繰り返すようにしなさい。