[updated on 1.10.22 for the 1.8.15 IDE version]
We will use the very basic blink sketch as an example:
void setup() { pinMode(13, OUTPUT); } void loop() { digitalWrite(13, HIGH); // set the LED on delay(1000); // wait for a second digitalWrite(13, LOW); // set the LED off delay(1000); // wait for a second }Use the following steps:
1. Compile the sketch inside the arduino IDE.
2. Go to your command prompt and navigate to the temporary compile folder. Mine was located here:
C:\Users\user\Documents\Arduino\Build
Note: Substitute your Windows Login ID for “Jim” in the above example, and the numbers after “build” will vary with each instance of compilation. Look for a folder that begins with “Build” which was created most recently inside of the “\Users\_your_id_here_\Documents\Arduino\” folder.
3. Enter the following command:
avr-objdump -S Blink.cpp.elf > list.txt
Note: “Blink.cpp.elf” is the name of your sketch with “.cpp.elf” appended to it, and “list.txt” is the name you choose for the file that will contain the assembly listing.
Note: avr-objdump.exe is located in the “\arduino-00xx\hardware\tools\avr\bin” folder and this folder must be in your PATH environment variable for this method to work.
9/3/2015 Note: Somewhere along the line of Adruino IDE updates, the temporary file folder structure has changed. While using IDE version 1.6.5, I noticed this new location for the output after compiling the example “blink” program:
C:\Users\James\AppData\Local\Temp\build4685747181797715506.tmp\sketch\Blink.cpp.elf
Here is the new temporary directory structure:
Note the file contents of each of these folders.
The “sketch” folder:
09/02/2015 08:12 AM 987 Blink.cpp
09/02/2015 08:12 AM 1,152 Blink.cpp.d
09/02/2015 08:13 AM 13 Blink.cpp.eep
09/02/2015 08:13 AM 15,539 Blink.cpp.elf
09/02/2015 08:13 AM 2,918 Blink.cpp.hex
09/02/2015 08:12 AM 4,176 Blink.cpp.o
09/02/2015 08:13 AM 4,272 Blink.cpp.with_bootloader.hex
The “core” folder:
09/02/2015 08:12 AM 166 abi.cpp.d
09/02/2015 08:12 AM 2,996 abi.cpp.o
09/02/2015 08:12 AM 1,062 CDC.cpp.d
09/02/2015 08:12 AM 2,492 CDC.cpp.o
09/02/2015 08:13 AM 397,254 core.a
09/02/2015 08:12 AM 1,282 HardwareSerial.cpp.d
09/02/2015 08:12 AM 28,104 HardwareSerial.cpp.o
09/02/2015 08:12 AM 1,284 HardwareSerial0.cpp.d
09/02/2015 08:12 AM 21,136 HardwareSerial0.cpp.o
09/02/2015 08:12 AM 1,284 HardwareSerial1.cpp.d
09/02/2015 08:12 AM 2,516 HardwareSerial1.cpp.o
09/02/2015 08:12 AM 1,284 HardwareSerial2.cpp.d
09/02/2015 08:12 AM 2,516 HardwareSerial2.cpp.o
09/02/2015 08:12 AM 1,284 HardwareSerial3.cpp.d
09/02/2015 08:12 AM 2,516 HardwareSerial3.cpp.o
09/02/2015 08:12 AM 166 hooks.c.d
09/02/2015 08:12 AM 2,168 hooks.c.o
09/02/2015 08:12 AM 1,342 IPAddress.cpp.d
09/02/2015 08:12 AM 14,324 IPAddress.cpp.o
09/02/2015 08:12 AM 1,152 main.cpp.d
09/02/2015 08:12 AM 4,844 main.cpp.o
09/02/2015 08:12 AM 166 new.cpp.d
09/02/2015 08:12 AM 4,744 new.cpp.o
09/02/2015 08:12 AM 1,173 PluggableUSB.cpp.d
09/02/2015 08:12 AM 2,512 PluggableUSB.cpp.o
09/02/2015 08:12 AM 1,066 Print.cpp.d
09/02/2015 08:12 AM 56,260 Print.cpp.o
09/02/2015 08:12 AM 1,068 Stream.cpp.d
09/02/2015 08:12 AM 43,148 Stream.cpp.o
09/02/2015 08:12 AM 1,064 Tone.cpp.d
09/02/2015 08:12 AM 19,764 Tone.cpp.o
09/02/2015 08:12 AM 1,163 USBCore.cpp.d
09/02/2015 08:12 AM 2,500 USBCore.cpp.o
09/02/2015 08:12 AM 545 WInterrupts.c.d
09/02/2015 08:12 AM 6,768 WInterrupts.c.o
09/02/2015 08:12 AM 535 wiring.c.d
09/02/2015 08:12 AM 8,400 wiring.c.o
09/02/2015 08:12 AM 549 wiring_analog.c.d
09/02/2015 08:12 AM 6,356 wiring_analog.c.o
09/02/2015 08:12 AM 551 wiring_digital.c.d
09/02/2015 08:12 AM 13,172 wiring_digital.c.o
09/02/2015 08:12 AM 547 wiring_pulse.c.d
09/02/2015 08:12 AM 10,108 wiring_pulse.c.o
09/02/2015 08:12 AM 1,688 wiring_pulse.S.o
09/02/2015 08:12 AM 547 wiring_shift.c.d
09/02/2015 08:12 AM 6,948 wiring_shift.c.o
09/02/2015 08:12 AM 170 WMath.cpp.d
09/02/2015 08:12 AM 8,292 WMath.cpp.o
09/02/2015 08:13 AM 262 WString.cpp.d
09/02/2015 08:13 AM 115,472 WString.cpp.o
Here is the resulting assembly listing:
blink.cpp.elf: file format elf32-avr Disassembly of section .text: 00000000 <__vectors>: timer0_millis = m; timer0_overflow_count++; } unsigned long millis() { 0: 60 c0 rjmp .+192 ; 0xc2 <__ctors_end> SREG = oldSREG; } } int digitalRead(uint8_t pin) { 2: 00 00 nop 4: 79 c0 rjmp .+242 ; 0xf8 <__bad_interrupt> 6: 00 00 nop 8: 77 c0 rjmp .+238 ; 0xf8 <__bad_interrupt> a: 00 00 nop c: 75 c0 rjmp .+234 ; 0xf8 <__bad_interrupt> e: 00 00 nop 10: 73 c0 rjmp .+230 ; 0xf8 <__bad_interrupt> 12: 00 00 nop 14: 71 c0 rjmp .+226 ; 0xf8 <__bad_interrupt> 16: 00 00 nop 18: 6f c0 rjmp .+222 ; 0xf8 <__bad_interrupt> 1a: 00 00 nop 1c: 6d c0 rjmp .+218 ; 0xf8 <__bad_interrupt> 1e: 00 00 nop 20: 6b c0 rjmp .+214 ; 0xf8 <__bad_interrupt> 22: 00 00 nop 24: 69 c0 rjmp .+210 ; 0xf8 <__bad_interrupt> 26: 00 00 nop 28: 67 c0 rjmp .+206 ; 0xf8 <__bad_interrupt> 2a: 00 00 nop 2c: 65 c0 rjmp .+202 ; 0xf8 <__bad_interrupt> 2e: 00 00 nop 30: 63 c0 rjmp .+198 ; 0xf8 <__bad_interrupt> 32: 00 00 nop 34: 61 c0 rjmp .+194 ; 0xf8 <__bad_interrupt> 36: 00 00 nop 38: 5f c0 rjmp .+190 ; 0xf8 <__bad_interrupt> 3a: 00 00 nop 3c: 5d c0 rjmp .+186 ; 0xf8 <__bad_interrupt> 3e: 00 00 nop 40: 6f c0 rjmp .+222 ; 0x120 <__vector_16> 42: 00 00 nop 44: 59 c0 rjmp .+178 ; 0xf8 <__bad_interrupt> 46: 00 00 nop 48: 57 c0 rjmp .+174 ; 0xf8 <__bad_interrupt> 4a: 00 00 nop 4c: 55 c0 rjmp .+170 ; 0xf8 <__bad_interrupt> 4e: 00 00 nop 50: 53 c0 rjmp .+166 ; 0xf8 <__bad_interrupt> 52: 00 00 nop 54: 51 c0 rjmp .+162 ; 0xf8 <__bad_interrupt> 56: 00 00 nop 58: 4f c0 rjmp .+158 ; 0xf8 <__bad_interrupt> 5a: 00 00 nop 5c: 4d c0 rjmp .+154 ; 0xf8 <__bad_interrupt> 5e: 00 00 nop 60: 4b c0 rjmp .+150 ; 0xf8 <__bad_interrupt> 62: 00 00 nop 64: 49 c0 rjmp .+146 ; 0xf8 <__bad_interrupt> ... 00000068 <port_to_mode_PGM>: 68: 00 00 00 00 24 00 27 00 2a 00 ....$.'.*. 00000072 <port_to_output_PGM>: 72: 00 00 00 00 25 00 28 00 2b 00 ....%.(.+. 0000007c <port_to_input_PGM>: 7c: 00 00 00 00 23 00 26 00 29 00 ....#.&.). 00000086 <digital_pin_to_port_PGM>: 86: 04 04 04 04 04 04 04 04 02 02 02 02 02 02 03 03 ................ 96: 03 03 03 03 .... 0000009a <digital_pin_to_bit_mask_PGM>: 9a: 01 02 04 08 10 20 40 80 01 02 04 08 10 20 01 02 ..... @...... .. aa: 04 08 10 20 ... 000000ae <digital_pin_to_timer_PGM>: ae: 00 00 00 07 00 02 01 00 00 03 04 06 00 00 00 00 ................ be: 00 00 00 00 .... 000000c2 <__ctors_end>: c2: 11 24 eor r1, r1 c4: 1f be out 0x3f, r1 ; 63 c6: cf ef ldi r28, 0xFF ; 255 c8: d8 e0 ldi r29, 0x08 ; 8 ca: de bf out 0x3e, r29 ; 62 cc: cd bf out 0x3d, r28 ; 61 000000ce <__do_copy_data>: ce: 11 e0 ldi r17, 0x01 ; 1 d0: a0 e0 ldi r26, 0x00 ; 0 d2: b1 e0 ldi r27, 0x01 ; 1 d4: e0 ee ldi r30, 0xE0 ; 224 d6: f3 e0 ldi r31, 0x03 ; 3 d8: 02 c0 rjmp .+4 ; 0xde <.do_copy_data_start> 000000da <.do_copy_data_loop>: da: 05 90 lpm r0, Z+ dc: 0d 92 st X+, r0 000000de <.do_copy_data_start>: de: a0 30 cpi r26, 0x00 ; 0 e0: b1 07 cpc r27, r17 e2: d9 f7 brne .-10 ; 0xda <.do_copy_data_loop> 000000e4 <__do_clear_bss>: e4: 11 e0 ldi r17, 0x01 ; 1 e6: a0 e0 ldi r26, 0x00 ; 0 e8: b1 e0 ldi r27, 0x01 ; 1 ea: 01 c0 rjmp .+2 ; 0xee <.do_clear_bss_start> 000000ec <.do_clear_bss_loop>: ec: 1d 92 st X+, r1 000000ee <.do_clear_bss_start>: ee: a9 30 cpi r26, 0x09 ; 9 f0: b1 07 cpc r27, r17 f2: e1 f7 brne .-8 ; 0xec <.do_clear_bss_loop> f4: 6f d1 rcall .+734 ; 0x3d4 <main> f6: 72 c1 rjmp .+740 ; 0x3dc <_exit> 000000f8 <__bad_interrupt>: f8: 83 cf rjmp .-250 ; 0x0 <__vectors> 000000fa <loop>: pinMode(13, OUTPUT); } void loop() { digitalWrite(13, HIGH); // set the LED on fa: 8d e0 ldi r24, 0x0D ; 13 fc: 61 e0 ldi r22, 0x01 ; 1 fe: 12 d1 rcall .+548 ; 0x324 <digitalWrite> delay(1000); // wait for a second 100: 68 ee ldi r22, 0xE8 ; 232 102: 73 e0 ldi r23, 0x03 ; 3 104: 80 e0 ldi r24, 0x00 ; 0 106: 90 e0 ldi r25, 0x00 ; 0 108: 53 d0 rcall .+166 ; 0x1b0 <delay> digitalWrite(13, LOW); // set the LED off 10a: 8d e0 ldi r24, 0x0D ; 13 10c: 60 e0 ldi r22, 0x00 ; 0 10e: 0a d1 rcall .+532 ; 0x324 <digitalWrite> delay(1000); // wait for a second 110: 68 ee ldi r22, 0xE8 ; 232 112: 73 e0 ldi r23, 0x03 ; 3 114: 80 e0 ldi r24, 0x00 ; 0 116: 90 e0 ldi r25, 0x00 ; 0 } 118: 4b c0 rjmp .+150 ; 0x1b0 <delay> 0000011a <setup>: void setup() { pinMode(13, OUTPUT); 11a: 8d e0 ldi r24, 0x0D ; 13 11c: 61 e0 ldi r22, 0x01 ; 1 } 11e: dc c0 rjmp .+440 ; 0x2d8 <pinMode> 00000120 <__vector_16>: volatile unsigned long timer0_overflow_count = 0; volatile unsigned long timer0_millis = 0; static unsigned char timer0_fract = 0; SIGNAL(TIMER0_OVF_vect) { 120: 1f 92 push r1 122: 0f 92 push r0 124: 0f b6 in r0, 0x3f ; 63 126: 0f 92 push r0 128: 11 24 eor r1, r1 12a: 2f 93 push r18 12c: 3f 93 push r19 12e: 8f 93 push r24 130: 9f 93 push r25 132: af 93 push r26 134: bf 93 push r27 unsigned long m = timer0_millis; 136: 80 91 04 01 lds r24, 0x0104 13a: 90 91 05 01 lds r25, 0x0105 13e: a0 91 06 01 lds r26, 0x0106 142: b0 91 07 01 lds r27, 0x0107 unsigned char f = timer0_fract; 146: 30 91 08 01 lds r19, 0x0108 m += MILLIS_INC; 14a: 01 96 adiw r24, 0x01 ; 1 14c: a1 1d adc r26, r1 14e: b1 1d adc r27, r1 f += FRACT_INC; 150: 23 2f mov r18, r19 152: 2d 5f subi r18, 0xFD ; 253 if (f >= FRACT_MAX) { 154: 2d 37 cpi r18, 0x7D ; 125 156: 20 f0 brcs .+8 ; 0x160 <__vector_16+0x40> f -= FRACT_MAX; 158: 2d 57 subi r18, 0x7D ; 125 m += 1; 15a: 01 96 adiw r24, 0x01 ; 1 15c: a1 1d adc r26, r1 15e: b1 1d adc r27, r1 } timer0_fract = f; 160: 20 93 08 01 sts 0x0108, r18 timer0_millis = m; 164: 80 93 04 01 sts 0x0104, r24 168: 90 93 05 01 sts 0x0105, r25 16c: a0 93 06 01 sts 0x0106, r26 170: b0 93 07 01 sts 0x0107, r27 timer0_overflow_count++; 174: 80 91 00 01 lds r24, 0x0100 178: 90 91 01 01 lds r25, 0x0101 17c: a0 91 02 01 lds r26, 0x0102 180: b0 91 03 01 lds r27, 0x0103 184: 01 96 adiw r24, 0x01 ; 1 186: a1 1d adc r26, r1 188: b1 1d adc r27, r1 18a: 80 93 00 01 sts 0x0100, r24 18e: 90 93 01 01 sts 0x0101, r25 192: a0 93 02 01 sts 0x0102, r26 196: b0 93 03 01 sts 0x0103, r27 } 19a: bf 91 pop r27 19c: af 91 pop r26 19e: 9f 91 pop r25 1a0: 8f 91 pop r24 1a2: 3f 91 pop r19 1a4: 2f 91 pop r18 1a6: 0f 90 pop r0 1a8: 0f be out 0x3f, r0 ; 63 1aa: 0f 90 pop r0 1ac: 1f 90 pop r1 1ae: 18 95 reti 000001b0 <delay>: return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond()); } void delay(unsigned long ms) { 1b0: 9b 01 movw r18, r22 1b2: ac 01 movw r20, r24 return m; } unsigned long micros() { unsigned long m; uint8_t oldSREG = SREG, t; 1b4: 7f b7 in r23, 0x3f ; 63 cli(); 1b6: f8 94 cli m = timer0_overflow_count; 1b8: 80 91 00 01 lds r24, 0x0100 1bc: 90 91 01 01 lds r25, 0x0101 1c0: a0 91 02 01 lds r26, 0x0102 1c4: b0 91 03 01 lds r27, 0x0103 #if defined(TCNT0) t = TCNT0; 1c8: 66 b5 in r22, 0x26 ; 38 #error TIMER 0 not defined #endif #ifdef TIFR0 if ((TIFR0 & _BV(TOV0)) && (t < 255)) 1ca: a8 9b sbis 0x15, 0 ; 21 1cc: 05 c0 rjmp .+10 ; 0x1d8 <delay+0x28> 1ce: 6f 3f cpi r22, 0xFF ; 255 1d0: 19 f0 breq .+6 ; 0x1d8 <delay+0x28> m++; 1d2: 01 96 adiw r24, 0x01 ; 1 1d4: a1 1d adc r26, r1 1d6: b1 1d adc r27, r1 #else if ((TIFR & _BV(TOV0)) && (t < 255)) m++; #endif SREG = oldSREG; 1d8: 7f bf out 0x3f, r23 ; 63 return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond()); } void delay(unsigned long ms) { uint16_t start = (uint16_t)micros(); 1da: ba 2f mov r27, r26 1dc: a9 2f mov r26, r25 1de: 98 2f mov r25, r24 1e0: 88 27 eor r24, r24 1e2: 86 0f add r24, r22 1e4: 91 1d adc r25, r1 1e6: a1 1d adc r26, r1 1e8: b1 1d adc r27, r1 1ea: 62 e0 ldi r22, 0x02 ; 2 1ec: 88 0f add r24, r24 1ee: 99 1f adc r25, r25 1f0: aa 1f adc r26, r26 1f2: bb 1f adc r27, r27 1f4: 6a 95 dec r22 1f6: d1 f7 brne .-12 ; 0x1ec <delay+0x3c> 1f8: bc 01 movw r22, r24 1fa: 2d c0 rjmp .+90 ; 0x256 <delay+0xa6> return m; } unsigned long micros() { unsigned long m; uint8_t oldSREG = SREG, t; 1fc: ff b7 in r31, 0x3f ; 63 cli(); 1fe: f8 94 cli m = timer0_overflow_count; 200: 80 91 00 01 lds r24, 0x0100 204: 90 91 01 01 lds r25, 0x0101 208: a0 91 02 01 lds r26, 0x0102 20c: b0 91 03 01 lds r27, 0x0103 #if defined(TCNT0) t = TCNT0; 210: e6 b5 in r30, 0x26 ; 38 #error TIMER 0 not defined #endif #ifdef TIFR0 if ((TIFR0 & _BV(TOV0)) && (t < 255)) 212: a8 9b sbis 0x15, 0 ; 21 214: 05 c0 rjmp .+10 ; 0x220 <delay+0x70> 216: ef 3f cpi r30, 0xFF ; 255 218: 19 f0 breq .+6 ; 0x220 <delay+0x70> m++; 21a: 01 96 adiw r24, 0x01 ; 1 21c: a1 1d adc r26, r1 21e: b1 1d adc r27, r1 #else if ((TIFR & _BV(TOV0)) && (t < 255)) m++; #endif SREG = oldSREG; 220: ff bf out 0x3f, r31 ; 63 void delay(unsigned long ms) { uint16_t start = (uint16_t)micros(); while (ms > 0) { if (((uint16_t)micros() - start) >= 1000) { 222: ba 2f mov r27, r26 224: a9 2f mov r26, r25 226: 98 2f mov r25, r24 228: 88 27 eor r24, r24 22a: 8e 0f add r24, r30 22c: 91 1d adc r25, r1 22e: a1 1d adc r26, r1 230: b1 1d adc r27, r1 232: e2 e0 ldi r30, 0x02 ; 2 234: 88 0f add r24, r24 236: 99 1f adc r25, r25 238: aa 1f adc r26, r26 23a: bb 1f adc r27, r27 23c: ea 95 dec r30 23e: d1 f7 brne .-12 ; 0x234 <delay+0x84> 240: 86 1b sub r24, r22 242: 97 0b sbc r25, r23 244: 88 5e subi r24, 0xE8 ; 232 246: 93 40 sbci r25, 0x03 ; 3 248: c8 f2 brcs .-78 ; 0x1fc <delay+0x4c> ms--; 24a: 21 50 subi r18, 0x01 ; 1 24c: 30 40 sbci r19, 0x00 ; 0 24e: 40 40 sbci r20, 0x00 ; 0 250: 50 40 sbci r21, 0x00 ; 0 start += 1000; 252: 68 51 subi r22, 0x18 ; 24 254: 7c 4f sbci r23, 0xFC ; 252 void delay(unsigned long ms) { uint16_t start = (uint16_t)micros(); while (ms > 0) { 256: 21 15 cp r18, r1 258: 31 05 cpc r19, r1 25a: 41 05 cpc r20, r1 25c: 51 05 cpc r21, r1 25e: 71 f6 brne .-100 ; 0x1fc <delay+0x4c> if (((uint16_t)micros() - start) >= 1000) { ms--; start += 1000; } } } 260: 08 95 ret 00000262 <init>: void init() { // this needs to be called before setup() or some functions won't // work there sei(); 262: 78 94 sei // on the ATmega168, timer 0 is also used for fast hardware pwm // (using phase-correct PWM would mean that timer 0 overflowed half as often // resulting in different millis() behavior on the ATmega8 and ATmega168) #if defined(TCCR0A) && defined(WGM01) sbi(TCCR0A, WGM01); 264: 84 b5 in r24, 0x24 ; 36 266: 82 60 ori r24, 0x02 ; 2 268: 84 bd out 0x24, r24 ; 36 sbi(TCCR0A, WGM00); 26a: 84 b5 in r24, 0x24 ; 36 26c: 81 60 ori r24, 0x01 ; 1 26e: 84 bd out 0x24, r24 ; 36 // this combination is for the standard atmega8 sbi(TCCR0, CS01); sbi(TCCR0, CS00); #elif defined(TCCR0B) && defined(CS01) && defined(CS00) // this combination is for the standard 168/328/1280/2560 sbi(TCCR0B, CS01); 270: 85 b5 in r24, 0x25 ; 37 272: 82 60 ori r24, 0x02 ; 2 274: 85 bd out 0x25, r24 ; 37 sbi(TCCR0B, CS00); 276: 85 b5 in r24, 0x25 ; 37 278: 81 60 ori r24, 0x01 ; 1 27a: 85 bd out 0x25, r24 ; 37 // enable timer 0 overflow interrupt #if defined(TIMSK) && defined(TOIE0) sbi(TIMSK, TOIE0); #elif defined(TIMSK0) && defined(TOIE0) sbi(TIMSK0, TOIE0); 27c: ee e6 ldi r30, 0x6E ; 110 27e: f0 e0 ldi r31, 0x00 ; 0 280: 80 81 ld r24, Z 282: 81 60 ori r24, 0x01 ; 1 284: 80 83 st Z, r24 // timers 1 and 2 are used for phase-correct hardware pwm // this is better for motors as it ensures an even waveform // note, however, that fast pwm mode can achieve a frequency of up // 8 MHz (with a 16 MHz clock) at 50% duty cycle TCCR1B = 0; 286: e1 e8 ldi r30, 0x81 ; 129 288: f0 e0 ldi r31, 0x00 ; 0 28a: 10 82 st Z, r1 // set timer 1 prescale factor to 64 #if defined(TCCR1B) && defined(CS11) && defined(CS10) sbi(TCCR1B, CS11); 28c: 80 81 ld r24, Z 28e: 82 60 ori r24, 0x02 ; 2 290: 80 83 st Z, r24 sbi(TCCR1B, CS10); 292: 80 81 ld r24, Z 294: 81 60 ori r24, 0x01 ; 1 296: 80 83 st Z, r24 sbi(TCCR1, CS11); sbi(TCCR1, CS10); #endif // put timer 1 in 8-bit phase correct pwm mode #if defined(TCCR1A) && defined(WGM10) sbi(TCCR1A, WGM10); 298: e0 e8 ldi r30, 0x80 ; 128 29a: f0 e0 ldi r31, 0x00 ; 0 29c: 80 81 ld r24, Z 29e: 81 60 ori r24, 0x01 ; 1 2a0: 80 83 st Z, r24 // set timer 2 prescale factor to 64 #if defined(TCCR2) && defined(CS22) sbi(TCCR2, CS22); #elif defined(TCCR2B) && defined(CS22) sbi(TCCR2B, CS22); 2a2: e1 eb ldi r30, 0xB1 ; 177 2a4: f0 e0 ldi r31, 0x00 ; 0 2a6: 80 81 ld r24, Z 2a8: 84 60 ori r24, 0x04 ; 4 2aa: 80 83 st Z, r24 // configure timer 2 for phase correct pwm (8-bit) #if defined(TCCR2) && defined(WGM20) sbi(TCCR2, WGM20); #elif defined(TCCR2A) && defined(WGM20) sbi(TCCR2A, WGM20); 2ac: e0 eb ldi r30, 0xB0 ; 176 2ae: f0 e0 ldi r31, 0x00 ; 0 2b0: 80 81 ld r24, Z 2b2: 81 60 ori r24, 0x01 ; 1 2b4: 80 83 st Z, r24 #if defined(ADCSRA) // set a2d prescale factor to 128 // 16 MHz / 128 = 125 KHz, inside the desired 50-200 KHz range. // XXX: this will not work properly for other clock speeds, and // this code should use F_CPU to determine the prescale factor. sbi(ADCSRA, ADPS2); 2b6: ea e7 ldi r30, 0x7A ; 122 2b8: f0 e0 ldi r31, 0x00 ; 0 2ba: 80 81 ld r24, Z 2bc: 84 60 ori r24, 0x04 ; 4 2be: 80 83 st Z, r24 sbi(ADCSRA, ADPS1); 2c0: 80 81 ld r24, Z 2c2: 82 60 ori r24, 0x02 ; 2 2c4: 80 83 st Z, r24 sbi(ADCSRA, ADPS0); 2c6: 80 81 ld r24, Z 2c8: 81 60 ori r24, 0x01 ; 1 2ca: 80 83 st Z, r24 // enable a2d conversions sbi(ADCSRA, ADEN); 2cc: 80 81 ld r24, Z 2ce: 80 68 ori r24, 0x80 ; 128 2d0: 80 83 st Z, r24 // here so they can be used as normal digital i/o; they will be // reconnected in Serial.begin() #if defined(UCSRB) UCSRB = 0; #elif defined(UCSR0B) UCSR0B = 0; 2d2: 10 92 c1 00 sts 0x00C1, r1 #endif } 2d6: 08 95 ret 000002d8 <pinMode>: #include "wiring_private.h" #include "pins_arduino.h" void pinMode(uint8_t pin, uint8_t mode) { uint8_t bit = digitalPinToBitMask(pin); 2d8: 48 2f mov r20, r24 2da: 50 e0 ldi r21, 0x00 ; 0 2dc: ca 01 movw r24, r20 2de: 86 56 subi r24, 0x66 ; 102 2e0: 9f 4f sbci r25, 0xFF ; 255 2e2: fc 01 movw r30, r24 2e4: 24 91 lpm r18, Z+ uint8_t port = digitalPinToPort(pin); 2e6: 4a 57 subi r20, 0x7A ; 122 2e8: 5f 4f sbci r21, 0xFF ; 255 2ea: fa 01 movw r30, r20 2ec: 84 91 lpm r24, Z+ volatile uint8_t *reg; if (port == NOT_A_PIN) return; 2ee: 88 23 and r24, r24 2f0: c1 f0 breq .+48 ; 0x322 <pinMode+0x4a> // JWS: can I let the optimizer do this? reg = portModeRegister(port); 2f2: e8 2f mov r30, r24 2f4: f0 e0 ldi r31, 0x00 ; 0 2f6: ee 0f add r30, r30 2f8: ff 1f adc r31, r31 2fa: e8 59 subi r30, 0x98 ; 152 2fc: ff 4f sbci r31, 0xFF ; 255 2fe: a5 91 lpm r26, Z+ 300: b4 91 lpm r27, Z+ if (mode == INPUT) { 302: 66 23 and r22, r22 304: 41 f4 brne .+16 ; 0x316 <pinMode+0x3e> uint8_t oldSREG = SREG; 306: 9f b7 in r25, 0x3f ; 63 cli(); 308: f8 94 cli *reg &= ~bit; 30a: 8c 91 ld r24, X 30c: 20 95 com r18 30e: 82 23 and r24, r18 310: 8c 93 st X, r24 SREG = oldSREG; 312: 9f bf out 0x3f, r25 ; 63 314: 08 95 ret } else { uint8_t oldSREG = SREG; 316: 9f b7 in r25, 0x3f ; 63 cli(); 318: f8 94 cli *reg |= bit; 31a: 8c 91 ld r24, X 31c: 82 2b or r24, r18 31e: 8c 93 st X, r24 SREG = oldSREG; 320: 9f bf out 0x3f, r25 ; 63 322: 08 95 ret 00000324 <digitalWrite>: } } void digitalWrite(uint8_t pin, uint8_t val) { uint8_t timer = digitalPinToTimer(pin); 324: 48 2f mov r20, r24 326: 50 e0 ldi r21, 0x00 ; 0 328: ca 01 movw r24, r20 32a: 82 55 subi r24, 0x52 ; 82 32c: 9f 4f sbci r25, 0xFF ; 255 32e: fc 01 movw r30, r24 330: 24 91 lpm r18, Z+ uint8_t bit = digitalPinToBitMask(pin); 332: ca 01 movw r24, r20 334: 86 56 subi r24, 0x66 ; 102 336: 9f 4f sbci r25, 0xFF ; 255 338: fc 01 movw r30, r24 33a: 34 91 lpm r19, Z+ uint8_t port = digitalPinToPort(pin); 33c: 4a 57 subi r20, 0x7A ; 122 33e: 5f 4f sbci r21, 0xFF ; 255 340: fa 01 movw r30, r20 342: 94 91 lpm r25, Z+ volatile uint8_t *out; if (port == NOT_A_PIN) return; 344: 99 23 and r25, r25 346: 09 f4 brne .+2 ; 0x34a <digitalWrite+0x26> 348: 44 c0 rjmp .+136 ; 0x3d2 <digitalWrite+0xae> // If the pin that support PWM output, we need to turn it off // before doing a digital write. if (timer != NOT_ON_TIMER) turnOffPWM(timer); 34a: 22 23 and r18, r18 34c: 51 f1 breq .+84 ; 0x3a2 <digitalWrite+0x7e> // //static inline void turnOffPWM(uint8_t timer) __attribute__ ((always_inline)); //static inline void turnOffPWM(uint8_t timer) static void turnOffPWM(uint8_t timer) { switch (timer) 34e: 23 30 cpi r18, 0x03 ; 3 350: 71 f0 breq .+28 ; 0x36e <digitalWrite+0x4a> 352: 24 30 cpi r18, 0x04 ; 4 354: 28 f4 brcc .+10 ; 0x360 <digitalWrite+0x3c> 356: 21 30 cpi r18, 0x01 ; 1 358: a1 f0 breq .+40 ; 0x382 <digitalWrite+0x5e> 35a: 22 30 cpi r18, 0x02 ; 2 35c: 11 f5 brne .+68 ; 0x3a2 <digitalWrite+0x7e> 35e: 14 c0 rjmp .+40 ; 0x388 <digitalWrite+0x64> 360: 26 30 cpi r18, 0x06 ; 6 362: b1 f0 breq .+44 ; 0x390 <digitalWrite+0x6c> 364: 27 30 cpi r18, 0x07 ; 7 366: c1 f0 breq .+48 ; 0x398 <digitalWrite+0x74> 368: 24 30 cpi r18, 0x04 ; 4 36a: d9 f4 brne .+54 ; 0x3a2 <digitalWrite+0x7e> 36c: 04 c0 rjmp .+8 ; 0x376 <digitalWrite+0x52> { #if defined(TCCR1A) && defined(COM1A1) case TIMER1A: cbi(TCCR1A, COM1A1); break; 36e: 80 91 80 00 lds r24, 0x0080 372: 8f 77 andi r24, 0x7F ; 127 374: 03 c0 rjmp .+6 ; 0x37c <digitalWrite+0x58> #endif #if defined(TCCR1A) && defined(COM1B1) case TIMER1B: cbi(TCCR1A, COM1B1); break; 376: 80 91 80 00 lds r24, 0x0080 37a: 8f 7d andi r24, 0xDF ; 223 37c: 80 93 80 00 sts 0x0080, r24 380: 10 c0 rjmp .+32 ; 0x3a2 <digitalWrite+0x7e> #if defined(TCCR2) && defined(COM21) case TIMER2: cbi(TCCR2, COM21); break; #endif #if defined(TCCR0A) && defined(COM0A1) case TIMER0A: cbi(TCCR0A, COM0A1); break; 382: 84 b5 in r24, 0x24 ; 36 384: 8f 77 andi r24, 0x7F ; 127 386: 02 c0 rjmp .+4 ; 0x38c <digitalWrite+0x68> #endif #if defined(TIMER0B) && defined(COM0B1) case TIMER0B: cbi(TCCR0A, COM0B1); break; 388: 84 b5 in r24, 0x24 ; 36 38a: 8f 7d andi r24, 0xDF ; 223 38c: 84 bd out 0x24, r24 ; 36 38e: 09 c0 rjmp .+18 ; 0x3a2 <digitalWrite+0x7e> #endif #if defined(TCCR2A) && defined(COM2A1) case TIMER2A: cbi(TCCR2A, COM2A1); break; 390: 80 91 b0 00 lds r24, 0x00B0 394: 8f 77 andi r24, 0x7F ; 127 396: 03 c0 rjmp .+6 ; 0x39e <digitalWrite+0x7a> #endif #if defined(TCCR2A) && defined(COM2B1) case TIMER2B: cbi(TCCR2A, COM2B1); break; 398: 80 91 b0 00 lds r24, 0x00B0 39c: 8f 7d andi r24, 0xDF ; 223 39e: 80 93 b0 00 sts 0x00B0, r24 // If the pin that support PWM output, we need to turn it off // before doing a digital write. if (timer != NOT_ON_TIMER) turnOffPWM(timer); out = portOutputRegister(port); 3a2: e9 2f mov r30, r25 3a4: f0 e0 ldi r31, 0x00 ; 0 3a6: ee 0f add r30, r30 3a8: ff 1f adc r31, r31 3aa: ee 58 subi r30, 0x8E ; 142 3ac: ff 4f sbci r31, 0xFF ; 255 3ae: a5 91 lpm r26, Z+ 3b0: b4 91 lpm r27, Z+ if (val == LOW) { 3b2: 66 23 and r22, r22 3b4: 41 f4 brne .+16 ; 0x3c6 <digitalWrite+0xa2> uint8_t oldSREG = SREG; 3b6: 9f b7 in r25, 0x3f ; 63 cli(); 3b8: f8 94 cli *out &= ~bit; 3ba: 8c 91 ld r24, X 3bc: 30 95 com r19 3be: 83 23 and r24, r19 3c0: 8c 93 st X, r24 SREG = oldSREG; 3c2: 9f bf out 0x3f, r25 ; 63 3c4: 08 95 ret } else { uint8_t oldSREG = SREG; 3c6: 9f b7 in r25, 0x3f ; 63 cli(); 3c8: f8 94 cli *out |= bit; 3ca: 8c 91 ld r24, X 3cc: 83 2b or r24, r19 3ce: 8c 93 st X, r24 SREG = oldSREG; 3d0: 9f bf out 0x3f, r25 ; 63 3d2: 08 95 ret 000003d4 <main>: #include <WProgram.h> int main(void) { init(); 3d4: 46 df rcall .-372 ; 0x262 <init> setup(); 3d6: a1 de rcall .-702 ; 0x11a <setup> for (;;) loop(); 3d8: 90 de rcall .-736 ; 0xfa <loop> 3da: fe cf rjmp .-4 ; 0x3d8 <main+0x4> 000003dc <_exit>: 3dc: f8 94 cli 000003de <__stop_program>: 3de: ff cf rjmp .-2 ; 0x3de <__stop_program>Avr-objdump.exe options:
Usage: avr-objdump
Display information from object .
At least one of the following switches must be given:
-a, --archive-headers Display archive header information
-f, --file-headers Display the contents of the overall file header
-p, --private-headers Display object format specific file header contents
-h, --[section-]headers Display the contents of the section headers
-x, --all-headers Display the contents of all headers
-d, --disassemble Display assembler contents of executable sections
-D, --disassemble-all Display assembler contents of all sections
-S, --source Intermix source code with disassembly
-s, --full-contents Display the full contents of all sections requested
-g, --debugging Display debug information in object file
-e, --debugging-tags Display debug information using ctags style
-G, --stabs Display (in raw form) any STABS info in the file
-W, --dwarf Display DWARF info in the file
-t, --syms Display the contents of the symbol table(s)
-T, --dynamic-syms Display the contents of the dynamic symbol table
-r, --reloc Display the relocation entries in the file
-R, --dynamic-reloc Display the dynamic relocation entries in the file
@ Read options from
-v, --version Display this program's version number
-i, --info List object formats and architectures supported
-H, --help Display this information
In versions up to .24 you may get this listings just by clicjing shift before the compile button. Sadly seems not to be working in version 1
Good technique, still works with Arduino IDE version1.8.7
Hi,
i wonder something inside this disassembly file. Where is the stack pointer initialize?
Register 0x3e and 0x3d are the SPH and SPL respectfully. So right here:
c6: cf ef ldi r28, 0xFF ; 255
c8: d8 e0 ldi r29, 0x08 ; 8
ca: de bf out 0x3e, r29 ; 62
cc: cd bf out 0x3d, r28 ; 61
Thanks for quick reply!
I read in some forums that the software reset is unsafe. The stack pointer could start from the wrong place, but now the stack pointer sets itself to the relevant address at the beginning without leaving it to us. Is it true?