A Place Where No Dreams Come True...

Current Topic: Sometimes it is just impossible to get critical timing correct when using a compiler. Not the compilers fault really. It generally has a better understanding of the machine then most programmers will ever have. But it also is very clever when optimizing code. Sometimes that can lead to logically correct code that may not meet timing requirements. And that's when an Assembler can come in real handy.

Assembly Language Maintains A One-To-One Relationship With Any Processor.

Assembly language is the first and original programming language. Before that it was machine code. Hard coded numbers based on tables contained on hundreds of pages of poorly copied documentation. Furthermore all processors implement their respective machine code differently. No two machines share the same binary requirements. However: Most machines share a very common set of mathematical, logical and data manipulation set of instructions. Assemblers are the lowest form of programming interpreters designed to abstract machine code into a language. Being the first though it is a very primitive language. Albeit with unlimited control.

It's because of the dissimilarities even in languages such as Assembly that led to the development of C. Only those programmers that have studied processor architecture and written a lot of ASM code truly understand how closely the C language is coupled to a processor. None the less even a seasoned programmer would find it difficult to beat a C compiler on ASM code.

So Why Even Consider Assembly Language Programming.

I don't think I would have ever considered AVR assembly coding except that I already had a vast history in embedded assembly programming (so no problem), and, I was trying to get maximum performance interfacing some persnickety hardware. Originally the compiler generated code close to as efficient, in fact close enough, but it had a tendency to defer (optimize) certain operations to when they were logically needed not where they were declared in the code (flow) effecting the timing of a critical operation.

Aside from simple interrupt service routines I only use assembly as a convenient (and efficient) method for direct hardware access. Without the Arduino abstractions.

Including Assembly Language In The Arduino Environment.

Aside from the tutorial on Assembly programming which is beyond the scope of this introduction the main interface to the Arduino environment is the accompanying header file that provides proper prototypes for the compiler and linker to resolve. These must be provided in the standard C format and must be bound by brackets containing an 'extern "C"' directive. To explain this, a very simple fragment of assembly code that is accessible to both C and C++ follows.

#define TEMPA R18
#define TEMPB R19

#define RPARAM1 R24
#define RPARAM2 R26

; Digit sync active low.
.equ REG_PORTA, 0X02
.equ REG_DDRA,  0X01
.equ REG_PINA,  0X00
; Segment source active high.
.equ REG_PORTC, 0X08
.equ REG_DDRC,  0X07
.equ REG_PINC,  0X06

;-----------------------------------------------------------------------------
.global led_init_strobe
led_init_strobe:
    LDI     TEMPA,0XFF
    OUT     REG_PORTA,TEMPA      ;
    LDI     TEMPA,0X00
    OUT     REG_PORTC,TEMPA      ;
    LDI     TEMPA,0XFF
    OUT     REG_DDRA,TEMPA       ;
    OUT     REG_DDRC,TEMPA       ;
    RET

;-----------------------------------------------------------------------------
.global led_enable_digit
led_enable_digit:
    OUT     REG_PORTA,RPARAM1    ;
    RET

;-----------------------------------------------------------------------------
.global led_write_segments
led_write_segments:
    OUT     REG_PORTC,RPARAM1    ;
    RET

The accompanying header file for this fragment would look something like this...

extern "C" {

#include <stdint.h>

void led_init_strobe(void);
void led_enable_digit(uint8_t);
void led_write_segments(uint8_t);

}

Notice that in this example parameters are passed from C (or C++). Parameters (any size or type) can freely be passed between C and Assembly. In both directions. The avr-gcc tools are quite specific on register usage and parameter passing convention.

Bottom Line.

Unless a program has a very special requirement (timing, hardware) it would be careless to assume that you could generate more efficient machine code then such a brilliant compiler. I have read several hundred pages of Atmel AVR processor specifications. And the compiler still understands more then I'll ever know.

It's got my trust.

10831