継続のためのArduinoのチューニングツールチェーン

むかしむかし、コード生成の予測可能性に非常に特定の要件があったArduinoでプロジェクトに取り組んでいたことがあり、ブラックボックスでの作業は場所によっては面倒でした。 そのため、組み立てプロセスをわずかに調整し、組み立て中にいくつかの追加手順を導入するというアイデアが生まれました。



ご存知のように、 Wiring言語は実際には本格的なC ++であり、ランタイム環境の重さのために例外のサポートが削除され、メイン関数の実装など、プログラムの構造に関連するいくつかの微妙さが隠され、開発者にはから呼び出されるセットアップおよびループ関数が与えられますメイン



これは、誰も話していない場合でも、C ++パンを使用できることを意味します。



この記事に記載されているすべては、少なくとも1.6以降のArduino環境のバージョンに適用されます。 私はすべてをWindowsで行いましたが、Linux / MacOSのアプローチは同じままで、技術的な詳細は変更されます。



それでは、始めましょう。



バージョン1.6環境では、GCCバージョン4.8コンパイラがデフォルトで使用されます。これには、デフォルトでC ++ 11のサポートが含まれていませんが、自動、可変テンプレート、およびその他の機能も必要です。 また、バージョン1.8の環境では、コンパイラーは既にバージョン4.9であり、デフォルトでC ++ 11をサポートしますが、右辺値参照、定数式、セパレーター、バイナリリテラル、およびその他の喜びを備えたC ++ 14の使用を強制することもできます。



デフォルトで含まれているよりも新しい標準のサポートを追加するには、コンパイル設定を含むArduinoインストールディレクトリのhardware\arduino\avr\platform.txt



ファイルを開き、 compiler.cpp.flags



パラメータを見つけて、目的の言語標準を指定します: -std=gnu++11



-std=gnu++14



置き換えます。 パラメータがない場合は、たとえば、行の最後に追加します。



ファイルを保存したら、スケッチの再構築を試すことができます-環境はすぐに新しい設定を取得します。



ここでは、 -Os



オプションを-Ofast



変更することで、よりコンパクトなコードではなく、最適化設定を変更して、より高速なコードの生成を有効にできます。



これらの設定はグローバルであるため、すべてのプロジェクトに適用できます。



次に、コンパイラーの結果をより詳細に制御することを決定し、ポストビルドイベントの類似物を追加しました。 これを行うには、 recipe.hooks.postbuild.0.pattern



パラメーターを同じファイルに追加します。このファイルの値には、アセンブリ後に起動されるファイルの名前とコマンドライン引数を含める必要があります。 値"{compiler.path}stat.bat" "{build.path}/{build.project_name}"



を割り当てました。 そのようなファイルはまだないので、 hardware\tools\avr\bin



(明らかにstat.bat



という名前で)作成する必要があります。



そこに次の行を書きましょう。



 "%~dp0\avr-objdump.exe" -d -C %1.elf > %1.SX "%~dp0\avr-nm.exe" %1.elf -nCS > %1.names
      
      





最初の行は、objdumpを使用して既にコンパイルおよび最適化されたプログラムの逆コンパイルを開始し、プロジェクト名と追加の拡張子.SXを使用して出力ファイルを作成します(選択は任意ですが、Sは伝統的にアセンブラーであり、Xは何らかの変換の事実を示します)。



2行目では、nmコマンドを実行してメモリ領域のシンボル名を抽出し、ファイルに追加の拡張子.namesを付けてレポートを生成しますが、ソートはアドレスで実行されます。



ここで、アセンブリが一時ディレクトリで実行されることを追加することも必要です。それを確認するには、Arduino設定に移動し、[詳細出力を表示]-> [コンパイル]チェックボックスをオンにします。 私の場合(IDEバージョン1.8.5)は、 %TEMP%\arduino_build_[random]



ようなディレクトリでした。



普通の生活で逆アセンブルされたコードを読むことは疑わしい喜びですが、誰かにとっては必要かもしれません(私はたまたま行ったことがあります)。



通常、名前のファイルの方が便利です。 ネタバレ-実験を行ったテストスケッチ:



テストスケッチ
 int counter = 1; void test(auto&& x) { static unsigned long time; long t = millis(); Serial.print(F("Counter: ")); Serial.println(counter); Serial.print(F(" At ")); Serial.print(t); Serial.print(F(" value is ")); Serial.println(x); Serial.print(F("Time between iterations: ")); Serial.println(t - time); Serial.println(); time = t; } void setup() { Serial.begin(9600); } void loop() { delay(100); test(digitalRead(A0)); }
      
      







結果の名前のファイル全体もネタバレです。



名前ファイル全体


w serialEvent()

00000000 W __heap_end

00000000 a __tmp_reg__

00000000 a __tmp_reg__

00000000 a __tmp_reg__

00000000 a __tmp_reg__

00000000 a __tmp_reg__

00000000 a __tmp_reg__

00000000 a __tmp_reg__

00000000 a __tmp_reg__

00000000 a __tmp_reg__

00000000 W __vector_default

00000000 T __vectors

00000001 a __zero_reg__

00000001 a __zero_reg__

00000001 a __zero_reg__

00000001 a __zero_reg__

00000001 a __zero_reg__

00000001 a __zero_reg__

00000001 a __zero_reg__

00000001 a __zero_reg__

00000001 a __zero_reg__

0000003d a __SP_L__

0000003d a __SP_L__

0000003d a __SP_L__

0000003d a __SP_L__

0000003d a __SP_L__

0000003d a __SP_L__

0000003d a __SP_L__

0000003d a __SP_L__

0000003d a __SP_L__

0000003e a __SP_H__

0000003e a __SP_H__

0000003e a __SP_H__

0000003e a __SP_H__

0000003e a __SP_H__

0000003e a __SP_H__

0000003e a __SP_H__

0000003e a __SP_H__

0000003e a __SP_H__

0000003f a __SREG__

0000003f a __SREG__

0000003f a __SREG__

0000003f a __SREG__

0000003f a __SREG__

0000003f a __SREG__

0000003f a __SREG__

0000003f a __SREG__

0000003f a __SREG__

00000068 T __trampolines_end

00000068 T __trampolines_start

00000068 0000001a t test(int)::__c

00000082 0000000b t test(int)::__c

0000008d 00000005 t test(int)::__c

00000092 0000000a t test(int)::__c

0000009c 00000014 T digital_pin_to_timer_PGM

000000b0 00000014 T digital_pin_to_bit_mask_PGM

000000c4 00000014 T digital_pin_to_port_PGM

000000d8 0000000a T port_to_input_PGM

000000e2 T __ctors_start

000000e4 T __ctors_end

000000e4 T __dtors_end

000000e4 T __dtors_start

000000e4 W __init

000000f0 00000016 T __do_copy_data

00000106 00000010 T __do_clear_bss

0000010e t .do_clear_bss_loop

00000110 t .do_clear_bss_start

00000116 00000016 T __do_global_ctors

00000134 T __bad_interrupt

00000134 W __vector_1

00000134 W __vector_10

00000134 W __vector_11

00000134 W __vector_12

00000134 W __vector_13

00000134 W __vector_14

00000134 W __vector_15

00000134 W __vector_17

00000134 W __vector_2

00000134 W __vector_20

00000134 W __vector_21

00000134 W __vector_22

00000134 W __vector_23

00000134 W __vector_24

00000134 W __vector_25

00000134 W __vector_3

00000134 W __vector_4

00000134 W __vector_5

00000134 W __vector_6

00000134 W __vector_7

00000134 W __vector_8

00000134 W __vector_9

00000138 00000012 T setup

0000014a 000000d8 T loop

00000222 00000094 T __vector_16

000002b6 00000018 T millis

000002ce 00000046 T micros

00000314 00000050 T delay

00000364 00000076 T init

000003da 00000052 t turnOffPWM

0000042c 00000052 T digitalRead

0000047e 00000016 T HardwareSerial::available()

00000494 0000001c T HardwareSerial::peek()

000004b0 00000028 T HardwareSerial::read()

000004d8 000000b8 T HardwareSerial::write(unsigned char)

00000590 000000a4 T HardwareSerial::flush()

00000634 0000001c W serialEventRun()

00000650 00000042 T HardwareSerial::_tx_udr_empty_irq()

00000692 000000d0 T HardwareSerial::begin(unsigned long, unsigned char)

00000762 00000064 T __vector_18

000007c6 0000004c T __vector_19

00000812 00000014 T Serial0_available()

00000826 00000086 t _GLOBAL__sub_I___vector_18

000008ac 00000002 W initVariant

000008ae 00000028 T main

000008d6 00000058 T Print::write(unsigned char const*, unsigned int)

000008ff W __stack

0000092e 0000004a T Print::print(__FlashStringHelper const*)

00000978 00000242 T Print::print(long, int)

00000bba 00000016 T Print::println()

00000bd0 0000029a T Print::println(int, int)

00000e6a 0000013a T Print::println(unsigned long, int)

00000fa4 00000002 t __empty

00000fa4 00000002 W yield

00000fa6 00000044 T __udivmodsi4

00000fb2 t __udivmodsi4_loop

00000fcc t __udivmodsi4_ep

00000fea 00000004 T __tablejump2__

00000fee 00000008 T __tablejump__

00000ff6 T _exit

00000ff6 W exit

00000ff8 t __stop_program

00000ffa A __data_load_start

00000ffa T _etext

00001016 A __data_load_end

00800100 D __data_start

00800100 00000002 D counter

00800102 00000010 V vtable for HardwareSerial

0080011c B __bss_start

0080011c D __data_end

0080011c D _edata

0080011c 00000004 b test(int)::time

00800120 00000001 b timer0_fract

00800121 00000004 B timer0_millis

00800125 00000004 B timer0_overflow_count

00800129 0000009d B Serial

008001c6 B __bss_end

008001c6 N _end

00810000 N __eeprom_end











読み方は? 正しくしましょう。



AVRコントローラには、プログラムメモリとデータメモリの2つの独立したメモリ領域があります。 したがって、コードへのポインターとデータへのポインターは同じものではありません。 EEPROMについては言及していませんが、アドレス指定については別の会話があります。 ダンプでは、プログラムメモリはオフセット0にあり、そこから実行が開始されます。また、要素ごとに4バイトの割り込みベクトルのテーブルもあります。 x86とは異なり、各割り込みベクトルにはハンドラーのアドレスは含まれませんが、実行する必要がある命令が含まれます。 通常(他のオプションを見たことがない)-jmp、つまり、目的のアドレスへの移行。 しばらくの間、割り込みベクターに戻りますが、今のところはさらに調べます。



データメモリは、オフセット0のレジスタファイルとオフセット0x100のランダムアクセスメモリ(SRAM)のデータの2つの部分で構成されています。 メモリダンプが出力されると、オフセット0x00800000がSRAMアドレスに追加されます。これは本質的には何も意味しませんが、便利です。 EEPROMオフセットの値は0x00810000ですが、これは必要ありません。



データから始めましょう。ここではすべてが少しシンプルでわかりやすいので、コードに戻ります。 最初の列はオフセット、2番目はサイズ、次にタイプ(注意を払うまで)、行の最後が名前です。



オフセット0x00800100に移動して、エントリを確認します。



 00800100 D __data_start 00800100 00000002 D counter 00800102 00000010 V vtable for HardwareSerial 0080011c D __data_end
      
      





.dataセクションに類似しており、初期化されたグローバル変数と静的変数、および仮想メソッドテーブルが含まれています。 これらの変数はブートストラップコードで初期化されますが、これには時間がかかります。



さらに進んでいきます(__bss_startと__data_endがランダムな順序で実行されることを気にしないでください-それらは共通のアドレスを持っています)。



 0080011c B __bss_start 0080011c 00000004 b test(int)::time 00800120 00000001 b timer0_fract 00800121 00000004 B timer0_millis 00800125 00000004 B timer0_overflow_count 00800129 0000009d B Serial 008001c6 B __bss_end
      
      





これは、初期化されていないデータのセクションです(.bssに類似)。 0バイトで埋められているため、何も与えられません。 いくつかのヘルパー変数、timer0_で始まる名前、グローバルシリアルオブジェクト、および静的ローカル変数を次に示します。



小さな叙情的な余談:Serialオブジェクトは最初は空であり、beginメソッドが呼び出されると初期化されることに注意してください。 これにはいくつかの理由があります。 第一に、それはまったく使用されないかもしれません(そして、それはまったく作成されず、それに割り当てられるスペースもありません)、第二に、グローバルオブジェクトの初期化の順序が定義されていないこと、そして厳密に言うと、コントローラー正しく初期化されていません。



上位アドレスに、スタックが配置されます。 コントローラのメモリが2キロバイト(atmega328プロセッサに基づくボード)の場合、最後のアドレスは0x008008FFになります。 このアドレスからスタックが始まり、アドレスの減少に向かって成長します。 障壁はありません。原則として、スタックは変数をクロールし、それらを破壊します。 または、データがスタックを破壊する可能性があります。 この場合、良いことは何も起こりません。 この未定義の動作を呼び出すことができますが、メモリにスタック用の十分なスペースを常に残しておくことをお勧めします。 どれだけ言いにくいか。 これは、すべての呼び出しのローカル変数とスタックフレームに加えて、すべてのネストされた呼び出しで最も重い割り込みハンドラーに十分でした。 正直に言って、スタックの使用を診断する方法について、多少なりとも正直な決定を見つけることはできませんでした。



コードに戻りましょう。 コードがそこに保存されていると言ったとき、私は少し不誠実でした。 実際、読み取り専用データはそこに格納できますが、それらはLPMプロセッサーからの特別な命令によってそこから抽出されます。 そのため、初期化に時間が無駄にならないため、定数データをそこに配置し、何のためにも配置することはできません。 コード内のマクロF(...)に注意してください。 プログラムメモリに配置された行を宣言するだけで、少し魔法をかけます。 魔法の詳細については触れませんが、記憶の中からそれらを探します。 このようなマクロはテスト関数に移動し、ダンプでは次のように表示されます



 00000068 0000001a t test(int)::__c 00000082 0000000b t test(int)::__c 0000008d 00000005 t test(int)::__c 00000092 0000000a t test(int)::__c
      
      





彼らは同じ名前を持っているという事実にもかかわらず、それらは異なるアドレスに位置しています。 マクロF(...)は中括弧でスコープを作成し、変数(より正確には定数)は互いに干渉しないためです。 逆アセンブルされたダンプを見ると、これらはプログラムメモリ内の行のアドレスになります。



そして最後に、約束された中断。 ライブラリは、周辺機器の動作をサポートするために、タイマー、通信インターフェイスなどのコントローラーリソースを使用します 割り込みハンドラを登録し、変数をメモリに保存し、定数をプログラムメモリに保存します。 空のスケッチをコンパイルすると、メモリダンプは次のようになります。



空のスケッチメモリダンプ
w serialEventRun()

00000000 W __heap_end

00000000 a __tmp_reg__

00000000 a __tmp_reg__

00000000 a __tmp_reg__

00000000 a __tmp_reg__

00000000 W __vector_default

00000000 T __vectors

00000001 a __zero_reg__

00000001 a __zero_reg__

00000001 a __zero_reg__

00000001 a __zero_reg__

0000003d a __SP_L__

0000003d a __SP_L__

0000003d a __SP_L__

0000003d a __SP_L__

0000003e a __SP_H__

0000003e a __SP_H__

0000003e a __SP_H__

0000003e a __SP_H__

0000003f a __SREG__

0000003f a __SREG__

0000003f a __SREG__

0000003f a __SREG__

00000068 T __ctors_end

00000068 T __ctors_start

00000068 T __dtors_end

00000068 T __dtors_start

00000068 W __init

00000068 T __trampolines_end

00000068 T __trampolines_start

00000074 00000010 T __do_clear_bss

0000007c t .do_clear_bss_loop

0000007e t .do_clear_bss_start

0000008c T __bad_interrupt

0000008c W __vector_1

0000008c W __vector_10

0000008c W __vector_11

0000008c W __vector_12

0000008c W __vector_13

0000008c W __vector_14

0000008c W __vector_15

0000008c W __vector_17

0000008c W __vector_18

0000008c W __vector_19

0000008c W __vector_2

0000008c W __vector_20

0000008c W __vector_21

0000008c W __vector_22

0000008c W __vector_23

0000008c W __vector_24

0000008c W __vector_25

0000008c W __vector_3

0000008c W __vector_4

0000008c W __vector_5

0000008c W __vector_6

0000008c W __vector_7

0000008c W __vector_8

0000008c W __vector_9

00000090 00000002 T setup

00000092 00000002 T loop

00000094 00000002 W initVariant

00000096 00000028 T main

000000be 00000094 T __vector_16

00000152 00000076 T init

000001c8 T _exit

000001c8 W exit

000001ca t __stop_program

000001cc A __data_load_end

000001cc a __data_load_start

000001cc T _etext

000008ff W __stack

00800100 B __bss_start

00800100 D _edata

00800100 00000001 b timer0_fract

00800101 00000004 B timer0_millis

00800105 00000004 B timer0_overflow_count

00800109 B __bss_end

00800109 N _end

00810000 N __eeprom_end







たくさんありませんか?



そして、ここにコードがあります:



逆アセンブルされたコード
 /empty.cpp.elf: file format elf32-avr Disassembly of section .text: 00000000 <__vectors>: 0: 0c 94 34 00 jmp 0x68 ; 0x68 <__ctors_end> 4: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt> 8: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt> c: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt> 10: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt> 14: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt> 18: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt> 1c: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt> 20: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt> 24: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt> 28: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt> 2c: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt> 30: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt> 34: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt> 38: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt> 3c: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt> 40: 0c 94 5f 00 jmp 0xbe ; 0xbe <__vector_16> 44: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt> 48: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt> 4c: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt> 50: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt> 54: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt> 58: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt> 5c: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt> 60: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt> 64: 0c 94 46 00 jmp 0x8c ; 0x8c <__bad_interrupt> 00000068 <__ctors_end>: 68: 11 24 eor r1, r1 6a: 1f be out 0x3f, r1 ; 63 6c: cf ef ldi r28, 0xFF ; 255 6e: d8 e0 ldi r29, 0x08 ; 8 70: de bf out 0x3e, r29 ; 62 72: cd bf out 0x3d, r28 ; 61 00000074 <__do_clear_bss>: 74: 21 e0 ldi r18, 0x01 ; 1 76: a0 e0 ldi r26, 0x00 ; 0 78: b1 e0 ldi r27, 0x01 ; 1 7a: 01 c0 rjmp .+2 ; 0x7e <.do_clear_bss_start> 0000007c <.do_clear_bss_loop>: 7c: 1d 92 st X+, r1 0000007e <.do_clear_bss_start>: 7e: a9 30 cpi r26, 0x09 ; 9 80: b2 07 cpc r27, r18 82: e1 f7 brne .-8 ; 0x7c <.do_clear_bss_loop> 84: 0e 94 4b 00 call 0x96 ; 0x96 <main> 88: 0c 94 e4 00 jmp 0x1c8 ; 0x1c8 <_exit> 0000008c <__bad_interrupt>: 8c: 0c 94 00 00 jmp 0 ; 0x0 <__vectors> 00000090 <setup>: 90: 08 95 ret 00000092 <loop>: 92: 08 95 ret 00000094 <initVariant>: 94: 08 95 ret 00000096 <main>: 96: 0e 94 a9 00 call 0x152 ; 0x152 <init> 9a: 0e 94 4a 00 call 0x94 ; 0x94 <initVariant> 9e: 0e 94 48 00 call 0x90 ; 0x90 <setup> a2: 80 e0 ldi r24, 0x00 ; 0 a4: 90 e0 ldi r25, 0x00 ; 0 a6: 89 2b or r24, r25 a8: 29 f0 breq .+10 ; 0xb4 <main+0x1e> aa: 0e 94 49 00 call 0x92 ; 0x92 <loop> ae: 0e 94 00 00 call 0 ; 0x0 <__vectors> b2: fb cf rjmp .-10 ; 0xaa <main+0x14> b4: 0e 94 49 00 call 0x92 ; 0x92 <loop> b8: 0e 94 49 00 call 0x92 ; 0x92 <loop> bc: fb cf rjmp .-10 ; 0xb4 <main+0x1e> 000000be <__vector_16>: be: 1f 92 push r1 c0: 0f 92 push r0 c2: 0f b6 in r0, 0x3f ; 63 c4: 0f 92 push r0 c6: 11 24 eor r1, r1 c8: 2f 93 push r18 ca: 3f 93 push r19 cc: 8f 93 push r24 ce: 9f 93 push r25 d0: af 93 push r26 d2: bf 93 push r27 d4: 80 91 01 01 lds r24, 0x0101 d8: 90 91 02 01 lds r25, 0x0102 dc: a0 91 03 01 lds r26, 0x0103 e0: b0 91 04 01 lds r27, 0x0104 e4: 30 91 00 01 lds r19, 0x0100 e8: 23 e0 ldi r18, 0x03 ; 3 ea: 23 0f add r18, r19 ec: 2d 37 cpi r18, 0x7D ; 125 ee: 20 f4 brcc .+8 ; 0xf8 <__vector_16+0x3a> f0: 01 96 adiw r24, 0x01 ; 1 f2: a1 1d adc r26, r1 f4: b1 1d adc r27, r1 f6: 05 c0 rjmp .+10 ; 0x102 <__vector_16+0x44> f8: 26 e8 ldi r18, 0x86 ; 134 fa: 23 0f add r18, r19 fc: 02 96 adiw r24, 0x02 ; 2 fe: a1 1d adc r26, r1 100: b1 1d adc r27, r1 102: 20 93 00 01 sts 0x0100, r18 106: 80 93 01 01 sts 0x0101, r24 10a: 90 93 02 01 sts 0x0102, r25 10e: a0 93 03 01 sts 0x0103, r26 112: b0 93 04 01 sts 0x0104, r27 116: 80 91 05 01 lds r24, 0x0105 11a: 90 91 06 01 lds r25, 0x0106 11e: a0 91 07 01 lds r26, 0x0107 122: b0 91 08 01 lds r27, 0x0108 126: 01 96 adiw r24, 0x01 ; 1 128: a1 1d adc r26, r1 12a: b1 1d adc r27, r1 12c: 80 93 05 01 sts 0x0105, r24 130: 90 93 06 01 sts 0x0106, r25 134: a0 93 07 01 sts 0x0107, r26 138: b0 93 08 01 sts 0x0108, r27 13c: bf 91 pop r27 13e: af 91 pop r26 140: 9f 91 pop r25 142: 8f 91 pop r24 144: 3f 91 pop r19 146: 2f 91 pop r18 148: 0f 90 pop r0 14a: 0f be out 0x3f, r0 ; 63 14c: 0f 90 pop r0 14e: 1f 90 pop r1 150: 18 95 reti 00000152 <init>: 152: 78 94 sei 154: 84 b5 in r24, 0x24 ; 36 156: 82 60 ori r24, 0x02 ; 2 158: 84 bd out 0x24, r24 ; 36 15a: 84 b5 in r24, 0x24 ; 36 15c: 81 60 ori r24, 0x01 ; 1 15e: 84 bd out 0x24, r24 ; 36 160: 85 b5 in r24, 0x25 ; 37 162: 82 60 ori r24, 0x02 ; 2 164: 85 bd out 0x25, r24 ; 37 166: 85 b5 in r24, 0x25 ; 37 168: 81 60 ori r24, 0x01 ; 1 16a: 85 bd out 0x25, r24 ; 37 16c: ee e6 ldi r30, 0x6E ; 110 16e: f0 e0 ldi r31, 0x00 ; 0 170: 80 81 ld r24, Z 172: 81 60 ori r24, 0x01 ; 1 174: 80 83 st Z, r24 176: e1 e8 ldi r30, 0x81 ; 129 178: f0 e0 ldi r31, 0x00 ; 0 17a: 10 82 st Z, r1 17c: 80 81 ld r24, Z 17e: 82 60 ori r24, 0x02 ; 2 180: 80 83 st Z, r24 182: 80 81 ld r24, Z 184: 81 60 ori r24, 0x01 ; 1 186: 80 83 st Z, r24 188: e0 e8 ldi r30, 0x80 ; 128 18a: f0 e0 ldi r31, 0x00 ; 0 18c: 80 81 ld r24, Z 18e: 81 60 ori r24, 0x01 ; 1 190: 80 83 st Z, r24 192: e1 eb ldi r30, 0xB1 ; 177 194: f0 e0 ldi r31, 0x00 ; 0 196: 80 81 ld r24, Z 198: 84 60 ori r24, 0x04 ; 4 19a: 80 83 st Z, r24 19c: e0 eb ldi r30, 0xB0 ; 176 19e: f0 e0 ldi r31, 0x00 ; 0 1a0: 80 81 ld r24, Z 1a2: 81 60 ori r24, 0x01 ; 1 1a4: 80 83 st Z, r24 1a6: ea e7 ldi r30, 0x7A ; 122 1a8: f0 e0 ldi r31, 0x00 ; 0 1aa: 80 81 ld r24, Z 1ac: 84 60 ori r24, 0x04 ; 4 1ae: 80 83 st Z, r24 1b0: 80 81 ld r24, Z 1b2: 82 60 ori r24, 0x02 ; 2 1b4: 80 83 st Z, r24 1b6: 80 81 ld r24, Z 1b8: 81 60 ori r24, 0x01 ; 1 1ba: 80 83 st Z, r24 1bc: 80 81 ld r24, Z 1be: 80 68 ori r24, 0x80 ; 128 1c0: 80 83 st Z, r24 1c2: 10 92 c1 00 sts 0x00C1, r1 1c6: 08 95 ret 000001c8 <_exit>: 1c8: f8 94 cli 000001ca <__stop_program>: 1ca: ff cf rjmp .-2 ; 0x1ca <__stop_program>
      
      







タイマー割り込み、このタイマーを処理するための9バイト、および一定量のインフラストラクチャコードが含まれます。



今日は、おそらく十分でしょう。 誰かが役に立つといいな。



All Articles