avr-gcc (und damit avr-as) erzeugen keinen Intel-Hex-Code.

Beim Compilieren entstehen folgende (temporären) Dateien:

*.c (C-Quelle)
*.i (precompilierte C-Quelle)
*.s (Assembly)
*.o (Object)
*.elf (elf32)

Beim Assemblieren:
*.s (Assembly)
*.o
*.elf

Wenn du nur compilierst (gcc -c ...), erhälst du ein Object-File (*.o), wenn du nur assemblierst (gcc -S ...) eine Assembler-Datei.

Aus den *.o bekommst du nach dem Link (avr-ld) mit deinen anderen Objekten ein *.elf.
Das elf enthält alle Informationen (auch debug-Info etc)

Wenn du nur 1 Quelle hast, kannst du die direkt übersetzen, as und ld werden von GCC aufgerufen (was abgeht siehst du mit GCC -v ...)

Ein hex bekommst du dann mit avr-objcopy aus dem elf:

avr-objcopy -j .text -j .data -O ihex foo.elf foo.hex

Daß die hex-Dateien nicht gleich sind, ist nicht verwunderlich.
Schliesslich übernimmt ld das Lokatieren und das Erstellen der vectab (wo die Interrupts stehen).
Ausserdem hatte ich die Wertetabellen nach hinten gelegt wegen der Übersicht.