3

I have a HEX file with a firmware for Attiny45. What I want to do is to extract some kind of formula that is coded inside it. I have done some research (mostly to find out that "it is not possible", etc, etc) but I decided I could give it a try since other parts of my research showed me that most of the people that ask this type of question barely knows what a HEX file is.

The objective of this post is not to came up with a brightly C code from the HEX file but rather build solid knowledge about the subject. I'm aware that the compiler, doing its job, can make my own job harder but there is some kind of structure (maybe primitive) that needs to be followed for the CPU to be able to execute the code.

So, I sat on my desk and coded a little Python tool to help me in the process. It loads the HEX file, and I interactively can add information to it. Here is what I've got so far:

The first line of the HEX file, says:

: 02 0000 04 0000 FA

Which was decoded by the tool to:

:       --> MARK
02      --> RECORD LENGTH
0000    --> LOAD OFFSET
04      --> RECORD TYPE (EXTENDED LINEAR ADDRESS RECORD)
0000    --> DATA
FA      --> CHECKSUM

Seems that this line serves the propose of telling that the initial address on which code should be put is 0x0000.

Second, the next line says:

: 20 0000 00 34C0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF50C07EEE7EB9 51

The tool decoded it to:

:    --> MARK
20   --> LENGHT OF THE RECORD
0000 --> OFFSET
00   --> RECORD TYPE (00 -> DATA RECORD) 34C0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF50C07EEE7EB9 (ACTUAL DATA)
51   --> CHECKSUM

Here is where the fun and the questions starts.

  1. I could not find anywhere the memory map of the ATTiny45. I thought it should be somewhere in the data sheet or the instruction set manual. From what I could figure out, at 0x0000 lives the interrupt vector (page 49, data sheet) and the first one is the reset vector. So, AVR being little endian and instructions being 16bits-wide, I can decode that the reset vector contains the value 0xC034. Using the instruction set, I figure out that 0xC034 is:

    rjump 0x034
    

    Is this correct?

  2. Continuing with this line of thinking, the same line pointed before shows that some of the interrupt vectors have values 0xFFFF, which causes me surprise but does not seem to be a problem since probably these will be disabled. The only other vector that have a working value is USI_OVF_ISR, which is equal to 0xC050. So, according to the ideas presented before, this says that USI_OVF_ISR has the instruction:

    rjump 0x050
    

    Is this also correct?

  3. If the reset vector points to 0x034, this says that the program will begin running at 0x034. The next line

    : 20 0020 00 7FE77FB9B89A089570EE7EB95FB9B89A08957EEE7EB9B898089570EE7EB9B898 22
    

    Shows that 0x034 is 0xB898 and that is the first instruction that will be executed.

    Is this correct?

2
  1. Seems to be almost correct, since the data sheet says in chapter 8.1, Resetting the AVR:

    The instruction placed at the Reset Vector must be a RJMP – Relative Jump – instruction to the reset handling routine

    However, page 202 - instruction set summary - explains RJMP like this:

    RJMP    k    Relative Jump PC   PC + k  + 1        
    

    Which would imply that RJMP at address PC=0 with a k=0x34 jumps to address 0x35.

    Unfortunately, the data sheet doesn't seem to have an opcode table to confirtm that C0 is indeed a RJMP.

    Also, Chapter 5.1 says

    The ATtiny25/45/85 contains 2/4/8K bytes On-chip In-System Reprogrammable Flash memory for program storage. Since all AVR instructions are 16 or 32 bits wide, the Flash is organized as 1024/2048/4096 x 16.

    and Chapter 9 shows a table (page 48) that has examples of RJMP instructions which, though they need 2 bytes, are packed into one address each. Starting at offset 0, and with 15 reset vectors that are 16 bits wide each, the program starts at address 0x0F. So the address space seems to be divided into 16-bit chunks per address, not 8-bit bytes, which would mean you have to double your addresses to get the appropriate byte index in your hex array.

  2. Seems incorrect to me, since PC is 0D (at offset 1A in your hex bytes) and r=50, so the RJMP should jump to 0D+50+1=5E, or offset BC (2*0x5E) in your hex bytes.

  3. According to my assumption that addresses denote 16-bit words, and adding the +1 from the opcode tab, you should probably look at 0x35*2=0x6A to find the first instruction to be executed.

| improve this answer | |

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.