Assembler listing reprise [SOLVED]

I'm now getting around to attempting the procedures below given by @Coding_Badly in this (now locked) thread in posts #5 & #7.

Using IDE 1.8.13, win10

Download then install any Python. I prefer 3.6 / 64 bit.

Did that.

Associate CPP files with your favourite editor. Or, download then install the free Visual Studio.

Did that and managed to open an .ino file. Unsure exactly how to know .cpp file are associated with VS - if indeed that's what the instruction means.

Put the batch file somewhere on your PATH.

Did that. It's not in any way functional, for now it's just a placeholder.

Now, my understanding is I need to

a. put the code from original post #5 into arduino assembler.bat then

b. name that file in the python script(?) and finally

c. invoke C:\Python64\python from a command prompt.

Am I missing any steps?

I'll start with that hurdle. Using File Explorer (the thing used to browse your harddrive) locate a dot-cpp file. Double click it. What program runs?

Since then Microsoft has made Visual Studio interminably slow to start. I've started using Notepad++ instead to get a "quick view" of source files.

Visual Studio was first among a list of options. I selected it and it came right up (sub one second on SSD).

List of options? Normally double-clicking launches without a prompt.

Oh well. Moving on...

You will need to remove arduino assembler.bat from that last entry. The PATH can only include directories; no files. (I assume arduino assembler.bat is a file based on the name.)

So a directory like - c:\documents\batfiles with the .bat contained in the batfiles directory is the goal?

Yes. Literally the only thing in it right now is 'some text'.

The path now looks like this:


And that folder now contains a renamed:

And the batch file contains the script(?) from the original thread post #5, copied with the button above the code slider.


The entire contents of the batch file should be...

@Echo Off

...where C:\Python64\python is the full path to python.exe. If python.exe is on the PATH then the directory is not necessary...

@Echo Off

Basically, the goal is to make the Python program (which runs the disassembler) as easy as possible to run.

I now have a batch file like so:

The content of the batch file is:


An explorer search turned up the commented out line but underscores in a path name don't look legitimate to me. But that's what the search found. I modified it to have backslashes instead just in case.

Have you placed in the Arduino_generate_assembler folder?

Seems like a lot of work, just to avoid becoming familiar with cmd.exe and a command-line interface...

Although... Does anyone know of a GUI tool designed specifically to browsing objdump output? I can find add-ons for Vi and EMACS, but that's not quite the same thing...

No. The only thing in the Arduino_generate_assembler folder is the batch file Arduino assembler batch.bat - which contains

@echo off
# C__Users_User_AppData_Local_Programs_Python_Python39_python_exe

The wasn't showing in the commented line, although I know I had put it there so I've added it to the commented line, too.

Thanks for your patience.

I tried this from the command line - because it used to work -

c:\Program Files (x86)\Arduino\hardware\tools\avr\bin>avr-objdump -d c:\users\user\appdata\local\temp\arduino_build_263156.ino.elf>printout.asm.lst

and got 'access denied' error. The SSD died last fall and had to be replaced so maybe that has something to do with it. Anyhow, rather than struggle constructing that line I decided to go for something more automated.

Hmm. Via TomZox's "Trowser"

Yes, but, when correctly setup ds from the command line pops open the current sketch disassembled. And, ds is (was) immune to IDE upgrades. That is crazy handy when optimizing.


Create a text file named in that same directory then put the following in that file...

import fnmatch
import os
import subprocess
import string

pathok = False
pathlist = os.environ['PATH'].split( os.pathsep )
for path in pathlist:
  testme = os.path.join(path,'avr-objdump.exe')
  if os.path.exists(testme):
    pathok = True

if not( pathok ):
  arduinoroot = 'C:\\Program Files (x86)\\Arduino\\'
  pathlist.append( arduinoroot + 'hardware\\tools\\avr\\utils\\bin' )
  pathlist.append( arduinoroot + 'hardware\\tools\\avr\\bin' )
  pathlist.append( arduinoroot + 'hardware\\tools\\avr\\etc' )
  pathnew = os.pathsep.join( pathlist )
  os.environ['PATH'] = pathnew

tempdir = os.environ.get('TEMP')
tempfile = os.path.join(tempdir,'Junk.cpp')

matches = []
for root, dirnames, filenames in os.walk(tempdir):
  for filename in fnmatch.filter(filenames, '*.elf'):
    matches.append(os.path.join(root, filename))

matches.sort( key=os.path.getmtime )

if len(matches) > 0:
  f = open(tempfile, 'w')['avr-objdump.exe','-S',matches[len(matches)-1]],stdout=f)
  os.system( 'start ' + tempfile )

To review:

a. VS associated with .cpp files

b. updated path to:

to test running just python No go.

c. Batch folder is:

d. I can run the Python script from its editor and a disassembled listing is produced in VS.

I can't get the path correct in the batch file to execute from there.


e. The listing generated doesn't show me what I expected. This Arduino sketch:

// compare mul vs shift and add
// X10 multiply uses the same flash and ram
// as the shift and add version

void setup() {

  int someValue = 528;

  int valX10Mul = someValue * 10;

  int valX10 = (someValue << 1) + (someValue << 3);

void loop() {


produces this in VS


I expected the assembler behind the two assignments statements to be shown. There's lots of other assembler but, not for this.

Welcome to "standard behavior" for a highly optimizing compiler. :frowning:

See how it's calling Print...constprop.3 ? If you go look at that code, it'll probably have the 5280 in it somewhere, and since that's the only call to Print, it's the only one needed.
(no, your inclusion of a bit of trivial math doesn't trick it in to not optimizing.)

Here it is (14A0 into r22,r23 ):

00000374 <Print::println(int, int) [clone .constprop.3]>:
  size_t n = print(b, base);
  n += println();
  return n;

size_t Print::println(int num, int base)
 374:   cf 93           push    r28
 376:   df 93           push    r29
    if (n < 0) {
      int t = print('-');
      n = -n;
      return printNumber(n, 10) + t;
    return printNumber(n, 10);
 378:   4a e0           ldi     r20, 0x0A       ; 10
 37a:   60 ea           ldi     r22, 0xA0       ; 160
 37c:   74 e1           ldi     r23, 0x14       ; 20
 37e:   80 e0           ldi     r24, 0x00       ; 0
 380:   90 e0           ldi     r25, 0x00       ; 0
 382:   0e 94 6c 01     call    0x2d8   ; 0x2d8 <Print::printNumber(unsigned long, unsigned char) [clone .constprop.8]>
 386:   ec 01           movw    r28, r24

Are you sure the Python path is correct? The executable being named "python89" is unexpected to me.

That wasn't a trick, it was the reason for revisiting this getting a listing thing. The sketch has two bits which do the multiplication in different ways. I found while experimenting that both used the same flash and ram. I was trying to see what the difference 'under the hood', if any, was. Turns out there was none. Still, after all that I have yet to discern where the multiplication is taking place. The output of VS is way different than what I have seen using the objdump route.