To quickly see the assembly code, in this case for an Arduino Duo with v1.5.4 of the Windows Arduino IDE, but other boards and Arduino IDE versions may be similar, first enable Verbose Output for compilation in the IDE preferences (File->Preferences). Then compile your code and look for a line like the following very near the bottom of the IDE's scrolling log.
C:\Program Files (x86)\Arduino/hardware/tools/g++_arm_none_eabi/bin/arm-none-eabi-objcopy -O binary C:\Users\kent\AppData\Local\Temp\build6841079203588404114.tmp/sketch_nov24a.cpp.elf
Paste this into a command window, modifying
objcopy
to objdump
. The path may vary depending on IDE version and Arduino board, e.g. AVR vs. SAM. If the wrong objdump
is used, you'll likely see an error about an unknown architecture.C:\Program Files (x86)\Arduino/hardware/tools/g++_arm_none_eabi/bin/arm-none-eabi-objdump -S C:\Users\kent\AppData\Local\Temp\build6841079203588404114.tmp/sketch_nov24a.cpp.elf
Several interesting options are available, but the
-S
option may be the nicest for dissembling as it will provide some source code context, but -d
and -D
are alternatives. To intermix the source code with the disassembly, it seems necessary to point objdump
to the directory with the sketch's .ino
source files using the -I
option, which the only indication if wrong is the absence of Arduino
source code in the disassembly. The default options to the compiler are
for this version of the Arduino IDE, include optimizing for code size (-Os
) and including debug symbols (-g
).Usage: C:\Program Files (x86)\Arduino\hardware\tools\g++_arm_none_eabi\bin\arm-none-eabi-objdump.exe <option(s)> <file(s)>
Display information from object <file(s)>.
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[lLiaprmfFsoR] or
--dwarf[=rawline,=decodedline,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=str,=loc,=Ranges]
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
@<file> Read options from <file>
-v, --version Display this program's version number
-i, --info List object formats and architectures supported
-H, --help Display this information
The following switches are optional:
-b, --target=BFDNAME Specify the target object format as BFDNAME
-m, --architecture=MACHINE Specify the target architecture as MACHINE
-j, --section=NAME Only display information for section NAME
-M, --disassembler-options=OPT Pass text OPT on to the disassembler
-EB --endian=big Assume big endian format when disassembling
-EL --endian=little Assume little endian format when disassembling
--file-start-context Include context from start of file (with -S)
-I, --include=DIR Add DIR to search list for source files
-l, --line-numbers Include line numbers and filenames in output
-F, --file-offsets Include file offsets when displaying information
-C, --demangle[=STYLE] Decode mangled/processed symbol names
The STYLE, if specified, can be `auto', `gnu',
`lucid', `arm', `hp', `edg', `gnu-v3', `java'
or `gnat'
-w, --wide Format output for more than 80 columns
-z, --disassemble-zeroes Do not skip blocks of zeroes when disassembling
--start-address=ADDR Only process data whose address is >= ADDR
--stop-address=ADDR Only process data whose address is <= ADDR
--prefix-addresses Print complete address alongside disassembly
--[no-]show-raw-insn Display hex alongside symbolic disassembly
--adjust-vma=OFFSET Add OFFSET to all displayed section addresses
--special-syms Include special symbols in symbol dumps
--prefix=PREFIX Add PREFIX to absolute paths for -S
--prefix-strip=LEVEL Strip initial directory names for -S
C:\Program Files (x86)\Arduino\hardware\tools\g++_arm_none_eabi\bin\arm-none-eabi-objdump.exe: supported targets: elf32-littlearm elf32-bigarm elf32-little elf32-big srec symbolsrec verilog tekhex binary ihex
C:\Program Files (x86)\Arduino\hardware\tools\g++_arm_none_eabi\bin\arm-none-eabi-objdump.exe: supported architectures: arm armv2 armv2a armv3 armv3m armv4 armv4t armv5 armv5t armv5te xscale ep9312 iwmmxt iwmmxt2
The following ARM specific disassembler options are supported for use with
the -M switch:
reg-names-special-atpcs Select special register names used in the ATPCS
reg-names-atpcs Select register names used in the ATPCS
reg-names-apcs Select register names used in the APCS
reg-names-std Select register names used in ARM's ISA documentation
reg-names-gcc Select register names used by GCC
reg-names-raw Select raw register names
force-thumb Assume all insns are Thumb insns
no-force-thumb Examine preceeding label to determine an insn's type
Report bugs to <https://support.codesourcery.com/GNUToolchain/>.
In the disassembled code, search for setup, loop, or whatever function you are interested in. Here a sample output segment is shown along with the Arduino source code. There is some unnecessary duplication in the intermixed source code.
C:\> <path_to_objdump>\objdump.exe -S -I <path_to_sketch_source_directory> <path_to_sketch_elf_file> | more
E.g.
C:\> "C:\Program Files (x86)\Arduino/hardware/tools/g++_arm_none_eabi/bin/arm-none-eabi-objdump" -S -I"C:\Users\kent\Documents\Arduino\test\sketch_nov24a" "C:\Users\kent\AppData\Local\Temp\build6841079203588404114.tmp/sketch_nov24a.cpp.elf" | more
00080124 <setup>:
void setup() {
80124: b508 push {r3, lr}
pinMode(31, OUTPUT);
80126: 201f movs r0, #31
80128: 2101 movs r1, #1
8012a: f000 f887 bl 8023c <pinMode>
8012e: 2380 movs r3, #128 ; 0x80
int v=0;
while(1) {
v = v ? 0 : 1<<7;
REG_PIOA_ODSR = v;
80130: 4a03 ldr r2, [pc, #12] ; (80140 <setup+0x1c>)
80132: 6013 str r3, [r2, #0]
void setup() {
pinMode(31, OUTPUT);
int v=0;
while(1) {
v = v ? 0 : 1<<7;
80134: 2b00 cmp r3, #0
80136: bf0c ite eq
80138: 2380 moveq r3, #128 ; 0x80
8013a: 2300 movne r3, #0
8013c: e7f8 b.n 80130 <setup+0xc>
8013e: bf00 nop
80140: 400e0e38 .word 0x400e0e38
The Arduino code:
void setup() {
pinMode(31, OUTPUT);
int v=0;
while(1) {
v = v ? 0 : 1<<7;
REG_PIOA_ODSR = v;
}
}
It would be handy to have disassembly functionality available from the IDE.