Being an "Assembler-freak" I am writing an Disassembler for the AT328P at that family.

So far so good.

But, now I ran into problems:

IF you write code like this:

.ORG $0000


BEGIN: LDI R16,$01


.ORG $100000 /* Much above 65 K */


and then you compile.

The Listing-file is correct but the HEX-file is SERIOUSLY wrong.

LISTING FILE (abbreviated)

000000 948c 0000 JMP START

000002 e001 BEGIN: LDI R16,$01


.org $100000

100000 940c 0002 START: JMP BEGIN

And the HEX-file (abbreviated - my indentation(s))

:020000020000FC :10 0000 00 8C94 0000 01E011E021E031E041E051E09A

:04 0000 00 0C94 0200 5A

The "8c94" and "0c94" are the JUMP instructions .

The Address part in the last line (:04 0000 00 0C94 0200 5A) // address = 0000 is wrong and should be 10 0000 .

Does anybody know how to fix that ?

Or Should we "implement / invent " a new ATMEL HEX format ?

Another thing with the INTEL-hex format is : IT does not clearly indicate when a code/data-segment starts or ends.

(As long as I keep the code within 65K - there's no problem - at all.)

KRis - NOrway

So you are rewriting avr-objdump, is that it?

The Address part in the last line (:04 0000 00 0C94 0200 5A) // address = 0000 is wrong and should be 10 0000 .

intel hex is limited to 16 bit addresses, and handles larger address by using a special record type (usually 4, I think) to load an offset. Presumably, that's somewhere in the part of the .hex file that you didn't include in your message.

Wikipedia says (

Allows for 32 bit addressing (up to 4GiB). The address field is ignored (typically 0000) and the byte count is always 02. The two encoded, big endian data bytes specify the upper 16 bits of the 32 bit absolute address for all subsequent type 00 records; these upper address bits apply until the next 04 record. If no type 04 record precedes a 00 record, the upper 16 address bits default to 0000. The absolute address for a type 00 record is formed by combining the upper 16 address bits of the most recent 04 record with the low 16 address bits of the 00 record.

2, I think.

Line format:
: = a colon
(All of below in hex format)
nn = length of data part
aaaa = address (eg. where to write data)
tt = transaction type
00 = data
01 = end of file
02 = extended segment address (changes high-order byte of the address)
03 = start segment address *
04 = linear address *
05 = start linear address *
(data) = variable length data
ss = sumcheck

I have code that reads those files:


@Nick Gammon,

First: Thanks for the link(s). IT sure helped me.

Second: You're quite right. No reason for (re-)inventing the wheel. But I did not know anything about AVR-OBJDUMP (or similar Code), so that's the reason.

And now the KRIS AVR - Disassembler is (pure) history .....(hehe)..

Third: I knew about the Intel HExformat and its limitations. But the extensions (code extension 03- 0x) (second part of your answer) I did not knew. Again thanks for the info.

The only thing in AVR-OBJDUMP I find a bit annoying is IT MUST be executed in DOS-MODE ( or Command-mode if you prefer that ).

Do you have any ideas of how to make a Windose (my nickname for W ) equivalent of OBJDUMP or how those ELF-files are constructed ?

(Is it easy (read: documentation is easy available) I might start a project based on a W -solution. )

Kris Norway

The code I posted above reads it. It's written in C++. Look at that. It shows you you decode one line, looking for formatting errors (eg. bad sumchecks). It works out the high-order byte from the type 02 record.

As for the disassembly part, well it can be done readily enough with a lookup table or two. I haven't written a dissembler for, like, 40 or more years, but it is a fun project, for sure.