The AVR Microcontroller and Embedded Systems Using Assembly and C

1バイト値をLSBから1ビットずつ出力する

p.249 #include <iostream> using namespace std; int main() { uint8_t byte = 0b11010100; // この1バイト値をLSBから1ビットずつ出力する。 /* // これがテキストと同じ方法 for(int i=0; i<8; i++){ if(byte & 1) printf("1,"); // ビット0に1が立っていたら1を出</iostream>…

1バイト値から10進数への変換例

p.247 整数 % 10で1の位を取り出す。 #include <iostream> using namespace std; int main(){ uint8_t byte = 253; // この1バイトデータを10進数に変換する(各桁を個別に取り出す)。 uint8_t ones = byte % 10; // (byte / 1) % 10; uint8_t tens = (byte / 10) % 10;</iostream>…

割り算

p.135 除算命令はない。除算演算子は使える。 .ORG 0 .DEF NUM = R20 ; .DEFはレジスタに名前をつけるためのディレクティブ。 .DEF DEN = R21 .DEF QUO = R22 LDI NUM, 100 LDI DEN, 15 CLR QUO ; Clear Register。レジスタ自身との排他的論理和をとる。 L1:…

アセンブリでLチカ

p.110 今わかっている範囲でLチカをしてみる。 .org 0 ldi r16, high(ramend) out SPH, r16 ldi r16, low(ramend) out SPL, r16 ; ldi r16, 0xff out DDRB, r16 ; ポートBのIOを全部OUTにして、 back: ldi r16, 0b00000010 out PORTB, r16 ; PB1からHを出力…

CALL命令とスタック

pp.86ff. ATmega328Pのデータシートを見るとSPの初期値はRAMENDになっているので初期化は不要かもしれない。 .org 0 ;;;;スタックポインタを初期化する ldi r16, high(ramend) ; RAMの末尾アドレス(16ビット)の上位バイトを、 out SPH, r16 ; スタックポイン…

分岐先アドレスの確認

p.83 BREQ命令を例にして分岐先アドレスを確認してみる。EQはif equal。 .org 00 ; ldi r16, 1 breq here ldi r16, 1 ldi r16, 1 ldi r16, 1 ldi r16, 1 ldi r16, 1 here: ldi r16, 1 ldi r16, 1 ldi r16, 1 breq here ldi r16, 1 ldi r16, 1

BRNE命令を使ったn重ループ

pp.78-80 .org 0 ; ldi r30, 0 ldi r31, 1 ; ldi r18, 2 ; r18を最外ループカウンターとして使う。 loop3: ldi r17, 3 ; r17を中間ループカウンターとして使う。 loop2: ldi r16, 4 ; r16を最内ループカウンターとして使う。 loop1: add r30, r31 ; 何かに何…

BRNE命令を使ったループ

pp.76-78 NEはif not equal。この方法だと255回までループできる。 .org 00 ; ldi r16, 5 ; r16をカウンターとして使う。 ldi r17, 0 ldi r18, 1 again: add r17, r18 ; 何かに何かを加算して、 dec r16 ; カウンターをデクリメントして、 brne again ; カウ…

リストファイル(.lss)

pp.57-58 ソースコード: .org 00 ldi r16, 0x25 ldi r17, 0x34 add r16, r17 sts 0x300, r16 sts 0x301, r17 生成されたリストファイル(.lss)の中身: 左列の6桁の数字がプログラム領域(フラッシュ)のアドレスである。 ldi r16, 0x25がe205に変換されるしくみ…

.EQUディレクティブ、.SETディレクティブ、.ORGディレクティブ、.INCLUDEディレクティブ

pp.47-48 ディレクティブはアセンブラへの指令。「pseudo命令」(疑似命令)とも言う。スードウ。 .EQUはequate。定数値または固定アドレスを定義するのに使う。 .equ sute = 2 ; 定数を定義する。 ldi r16, sute .equ where = 0x100 ; アドレスを定義する。 l…

ステータスレジスタ(SREG)

pp.41-42 「flag register」とも言う。レジスタ。 C~Hが「conditional flags (条件フラグ)」。 Cはcarryフラグ。一般に符号なし演算のエラー検出に使う。 Zはzeroフラグ。結果が0のときにフラグが立つ。 Nはnegativeフラグ。結果のビット[7]が1のときにフラ…

MOV命令、INC命令、SUB命令、DEC命令、COM命令

pp.37-40 MOVはGPR同士で値をコピーし合う命令。 INCはGPRの値を1だけインクリメントする命令。 SUBはADDの逆。 DECはGPRの値を1だけデクリメントする命令。 COMはcomplement (1の補数)。~と同じ。 ldi r16, 0xa ; r16に即値をロードする。 mov r0, r16 ; r0…

IN命令、OUT命令

pp.34-36 INは、I/OレジスタからGPRへ1バイトをロードする命令。 I/OメモリーのアドレスはI/Oアドレスとデータメモリーアドレスの2つがある。データメモリーのアドレスは、「データメモリーアドレス」と呼ばれる一意のアドレスである。また各I/Oレジスタ(Spe…

LDS命令、STS命令

pp.32-34 LDSはLoad Direct from Data Space。 データ空間(IOレジスタ、SRAM、GPR)から汎用レジスタ(GPR)へ値をロードする。 STSはStore Direct to Data Space。 汎用レジスタ(GPR)の値をデータ空間(IOレジスタ、SRAM、GPR)へストアする。 ldi r16, 0x55 ; r…

LDI命令、ADD命令

特に断らない限りATmega328Pを使う。 pp.27-28 汎用レジスタはR0~R31の32本あるが、LDIでロードできるのはR16~R31のみ。LDIのIはImmediate。即値。イミーディアトゥ。 LDI R16, 1 ; レジスタR16に10進数の1を格納する。 LDI R17, 0b10101010 ; 2進数の LDI…