5

My source files are *.ino, but after compilation there aren't any other files placed in the folder. Does the compiler generate intermediate assembler, and if so, where does it leave them? Or is the machine code available somewhere?

4
  • 1
    1) If you switch to a Makefile build or in some other way can customize arguments then you can ask avr-gcc to produce assembler ouput. 2) Alternately you can use avr-objdump to disassemble binary (or with the aid of objcopy, hex) ouput back to assembly mnemonics. With an original unstripped elf binary objdump may be able to print many symbols (the usual way of producing a list file), but with a raw binary or hex file those are permanently lost. – Chris Stratton Feb 9 '15 at 15:45
  • @ChrisStratton: Thanks. Can you elaborate on 1)? I know makefiles are commonly used by software developers, but I don't have any experience with them. – Joris Groosman Feb 9 '15 at 15:56
  • There are various stock Makefiles you can find online to build an Arduino project with greater control of the details. Not able to dig one up for you right now. There may also be ways to customize the IDE's commands, but the IDE has so many other problems I'm not sure it's worth the bother. – Chris Stratton Feb 9 '15 at 15:58
  • You can find Arduino compatible makefiles in the embedxcode repository at embedxcode.weebly.com You will probably look at the arduino15avr.mk file in particular. You can change this file to have assembler output save and place where you want it to be. – MAC Feb 9 '15 at 18:45
6

My source files are *.ino, but after compilation there aren't any other files placed in the folder.

Correct. The Arduino IDE performs compilation in a separate temporary directory, whose location you can see if you enable verbose compilation in the IDE options.

Does the compiler generate intermediate assembler, and if so, where does it leave them?

By default GCC (which the Arduino IDE uses) does not leave intermediate assembly language files on disk. You must pass the --save-temps argument to have it leave them in the current directory, or --save-temps=obj to save them in the output directory.

Or is the machine code available somewhere?

The machine code is available in the .elf and .hex files generated in the temprary directory.

1

Yes.

Arduino compilation is set up with link-time optimization (LTO), and the assembly files created during C compilation don't contain any assembly code - just the intermediate representation used later in the LTO stage to generate actual assembly code. We want the latter.

It so happens, rather nicely, that the very last time assembler is invoked in the entire compilation process, is to take the output from the LTO stage, and turn it into a whole-application object file.

To get at this assembly file, do the following (on Windows):

  1. Open %LOCALAPPDATA%\Arduino15\packages\arduino\hardware\avr\1.8.3\platform.local.txt (create it if it doesn't exist). Add the following line

    compiler.c.elf.extra_flags=-save-temps=obj -fverbose-asm
    

    If there already is such a line there, just add the above options (to the right of =).

    Note: If you can't find the folder, look for the following files: boards.txt, platform.txt, programmers.txt. If you find these files in multiple locations, the one you want should be inside your home directory (i.e. not in Program Files or /Applications or /usr), and should be correlated at least partially to the version of Arduino you're using (should you have multiple versions installed).

  2. Build the sketch again.

  3. Look for a file named %TEMP%\cc*.ltrans.s. Each build will create a new such file. If you sort them by timestamp, the newest one is for the most recent build.

Note: The environment variables, enclosed by % signs, are valid in the Windows dialog boxes. You can directly paste such a path into e.g. an Open or Save As... dialog box, and it'll work. Paths with globs (*) will act as filters (IIRC).

To know which exact cc*.s file was generated, add the verbose option to the final binary generator pass:

compiler.c.elf.extra_flags=-save-temps=obj -fverbose-asm -v

Rebuild, and copy-paste all the output from the compilation status window in Arduino to e.g. Notepad++, and search for ar.exe. The sole line that contains ar.exe ends with the name of this cc file:

 c:/users/[...omitted...]/avr/bin/as.exe -mmcu=avr6 -mno-skip-bug 
    -o C:\Users\[...]\AppData\Local\Temp\cc3XhU2F.ltrans0.ltrans.o
    C:\Users\[...]\AppData\Local\Temp\cc3XhU2F.ltrans0.ltrans.s

How does the file look? This is a short extract, just to show that both the C source and the assembly are intermingled - and this represents exactly the binary embedded in the .hex file and sent to the target.

.LBE33:
.LBE32:
.LBB34:
.LBB35:
 ;  C:\Users\[...]\Documents\Arduino\sketch_jul01a\sketch_jul01a.ino:29:   pinMode(ledPin, OUTPUT);
    .file 4 "C:\\Users\\[...]\\Documents\\Arduino\\sketch_jul01a\\sketch_jul01a.ino"
    .loc 4 29 0
    ldi r22,lo8(1)   ; ,
    ldi r24,lo8(13)  ; ,
    call pinMode     ; 
.LVL55:
 ;  C:\Users\[...]\Documents\Arduino\sketch_jul01a\sketch_jul01a.ino:30:   pinMode(relayPin, OUTPUT);
    .loc 4 30 0
    ldi r22,lo8(1)   ; ,
    ldi r24,lo8(12)  ; ,
    call pinMode     ; 
.LVL56:
 ;  C:\Users\[...]\Documents\Arduino\sketch_jul01a\sketch_jul01a.ino:31:   pinMode(ldrPin, INPUT);
    .loc 4 31 0
    ldi r22,0    ; 
    ldi r24,lo8(54)  ; ,
    call pinMode     ; 
.LVL57:
.LBE35:
.LBE34:
.LBB36:
.LBB37:

This approach also works on Linux and MacOS, except that the paths are slightly different, and path expansion uses different syntax. The two files of concern still are platform.local.txt - a file you must create, since it doesn't exist at first, and the ${TEMP}/cc*.ltrans.s files.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.