How can I program an Arduino in pure assembly? (Possibly solved...)

I have an Arduino Uno (SMD Edition) and I'd like to program it in pure assembly language. I've done some Googling on the subject, and from what I found on this forum and on other sites (Stack Overflow, avrfreaks.net, etc.) you can only do this by:

  • Having an ISP programmer (like Sparkfun's Pocket AVR Programmer, or USBtinyISP, or one from Atmel, etc.)
  • Using inline assembly in the Arduino IDE

Now, I don't have a programmer. I'd rather not buy one if I don't have to, and I don't want to wait for it to arrive. I also don't want to use inline assembly because that's still not pure assembly.

Here is my possible solution. It works, but I'd like your criticism. I'm very new to Arduino and AVR, so please correct my misunderstandings:

  • I turned on the verbose options within the Arduino IDE. I saw that after compilation, the command C:\somepath\avrdude -C C:\somepath\avrdude.conf -v -p atmega328p -c arduino -P \\.\COM5 -b 115200 -D -U flash:w:C\somepath\sketch.hex:i was being run to program the Arduino.
  • I downloaded Atmel Studio 6.1, created a new project targeted at the ATmega328P, and wrote out some very basic assembly to flash an LED. I used the tutorial at http://www.avrbeginners.net/ to get me started.
  • I compiled the code in Atmel Studio, which produced another .hex file. This file is MUCH MUCH shorter than the .hex files produced by the Arduino IDE.
  • I re-ran the avrdude command that I saw the Arduino IDE. I used the AVRdude provided with the Arduino IDE installation, though I tried installing a separate version (part of WinAVR I think) which didn't work. I of course switched out the .hex files.

I was surprised to find that this worked. I sent pure assembly code compiled by Atmel Studio to the ATmega328P on my Arduino that ran. Moreover, it didn't prevent me from later using the Arduino IDE to upload a different sketch- that is, it didn't appear to affect the bootloader or any other "magic" that the Arduino uses to make programming easy.

Is this a good solution, or am I misunderstanding what's going on?

It works, but I'd like your criticism. I'm very new to Arduino and AVR, so please correct my misunderstandings:

Think you used the right steps

imho you should only use assembly if you

  • are running out of memory
  • need raw speed
  • another processor(HW) is no option

Maintaining / debugging a complete asm prog is (can be) difficult,
but you really learn how things work under the hood.

This file is MUCH MUCH shorter

Every compiler adds some standard code ( lookup tables, some init routines etc ) to executables and that increases the size of the hex files.
An empty Arduino sketch is about 500 bytes. An empty ASM might be as small as a few bytes JMP to itself.

I would appreciate if you share your ASM code examples as I expect more people on the forum are interested.

Hi Rob,

Thanks for the clarification. I'm a university student, so I'm deliberately trying to use ASM as a learning experience, not to accomplish any real work.

Here's the code I used. I haven't looked up every single instruction in the Atmel manual, some of it is just copied. It works as expected though. On my Arduino, blinking an LED over pin 13 also lights an LED on the circuit board, making it easy to verify that the code is working without setting up any other circuit. I just compile the code in Atmel Studio and then use the AVRdude command line program included with the Arduino IDE to upload it.

/*
 * Get an LED blinking on the ATmega328 (Arduino)
 * On Arduino, pin 13 has an on-board LED which blinks. Pin 13 should map to PB5 (SCK/PCINT5) on the MCU.
 */ 

 .ORG	0x0000					// Tells the next instruction to be written
 RJMP	main					// State that the program begins at the main label

 main:
 LDI	r16, 0xFF				// Load the immedate value 0xFF (all bits 1) into register 16
 OUT	DDRB, r16				// Set Data Direction Register B to output for all pins

 loop:
 SBI	PortB, 5				// Set the 5th bit in PortB. (i.e. turn on the LED)
 RCALL	delay_05
 CBI	PortB, 5				// Clear the 5th bit in PortB. (i.e. turn off the LED)
 RCALL	delay_05
 RJMP	loop					// Loop again

 // Not sure what any of this does, it should be a delay loop though
 delay_05:
 LDI	r16, 8

 outer_loop:
 LDI	r24, low(3037)
 LDI	r25, high(3037)

 delay_loop:
 ADIW	r24, 1
 BRNE	delay_loop
 DEC	r16
 BRNE	outer_loop
 RET

and the hex size of this "proze" is ?

// Not sure what any of this does, it should be a delay loop though

it definitely is a delay loop, tried to C-ify the assembly

delay_05()
{
    uint8_t A = 8;           // LDI	r16, 8
    do                       // outer_loop:
    {                        
        uint16_t B = 3037;   // LDI	r24, low(3037)
                             // LDI	r25, high(3037) 
        do                   // delay_loop:  
        {                      
            B++;             // ADIW	r24, 1   
        } while (B != 0);    // BRNE	delay_loop
        A--;                 // DEC	r16
    } while (A != 0);        // BRNE	outer_loop
}                            // RET

so the loop runs about 8 * (65536-3037) = 499992 times.

Hello, I'm currently trying to also learn using assembly language for arduino project, but having problem of flashing it without a programmer (ie. AVRDragon,AVROne). I came across this thread and though it was a good soluton to my problem. Can you provide a step by step on how to do it? If possble with picture guide. And can i use old AVR Studio (ie. AVR Studio 4) to do it? Thank you

32 bits MIPS Assembly Language at Arduino Yun by GCC

http://forum.arduino.cc/index.php?topic=266549.msg1879510#msg1879510