views:

329

answers:

2

I have a binary file that I've disassembled using avr-objcopy. The interrupt vector table looks like:

00000000 :
    ; VECTOR TABLE
   0:   13 c0        rjmp .+38      ;  0x28, RESET
   2:   b8 c1        rjmp .+880     ;  0x374, INT0
   4:   fd cf        rjmp .-6       ;  0x0
   6:   fc cf        rjmp .-8       ;  0x0
   8:   fb cf        rjmp .-10      ;  0x0
   a:   fa cf        rjmp .-12      ;  0x0
   c:   f9 cf        rjmp .-14      ;  0x0
   e:   f8 cf        rjmp .-16      ;  0x0
  10:   f7 cf        rjmp .-18      ;  0x0
  12:   c7 c1        rjmp .+910     ;  0x3a2, TIMER1 OVF
  14:   f5 cf        rjmp .-22      ;  0x0
  16:   f4 cf        rjmp .-24      ;  0x0
  18:   f3 cf        rjmp .-26      ;  0x0
  1a:   f2 cf        rjmp .-28      ;  0x0
  1c:   2b c2        rjmp .+1110    ;  0x474, ADC conversion complete
  1e:   f0 cf        rjmp .-32      ;  0x0
  20:   ef cf        rjmp .-34      ;  0x0
  22:   ee cf        rjmp .-36      ;  0x0
  24:   ed cf        rjmp .-38      ;  0x0
  26:   00 00        nop
  ; START
  28:   f8 94        cli
 (snip)
I want to reassemble this file with a few modifications. I've reformatted it by removing the first 2 columns so that it is a regular assembly file. ie:
.org 0
    rjmp    .+38            ;  0x28, RESET
    rjmp    .+880           ;  0x374, INT0
(snip)
However, when I run
$ avr-as -mmcu=atmega8 test.asm
and then disassemble the generated file. (using objcopy -S a.out) The output looks like:
00000000 :
   0:   00 c0           rjmp    .+0             ;  0x2
   2:   00 c0           rjmp    .+0             ;  0x4
   4:   00 c0           rjmp    .+0             ;  0x6
   6:   00 c0           rjmp    .+0             ;  0x8
   8:   00 c0           rjmp    .+0             ;  0xa
   a:   00 c0           rjmp    .+0             ;  0xc
   c:   00 c0           rjmp    .+0             ;  0xe
   e:   00 c0           rjmp    .+0             ;  0x10
  10:   00 c0           rjmp    .+0             ;  0x12
  12:   00 c0           rjmp    .+0             ;  0x14
  14:   00 c0           rjmp    .+0             ;  0x16
  16:   00 c0           rjmp    .+0             ;  0x18
  18:   00 c0           rjmp    .+0             ;  0x1a
  1a:   00 c0           rjmp    .+0             ;  0x1c
  1c:   00 c0           rjmp    .+0             ;  0x1e
  1e:   00 c0           rjmp    .+0             ;  0x20
  20:   00 c0           rjmp    .+0             ;  0x22
  22:   00 c0           rjmp    .+0             ;  0x24
  24:   00 c0           rjmp    .+0             ;  0x26
  26:   00 00           nop
  28:   f8 94           cli
(snip)

So how can I get avr-as to respect the PC-relative jumps?

A: 

I'm assuming that rjmp PC+2 doesnt work in avr-as ? That's how I'd do it in AVR Studio...

Len Holgate
Thanks for the tip. I tried it but it doesn't work. :(In fact the only time that I have been able to get it disassemble to something other than "rjmp .+0" is when I use a literal. But then it is no longer relative, but absolute.
kroylar
+2  A: 

I found the answer!

I was assembling but not linking. So the assembler was filling in all relative jumps/calls/branches with .+0.

To fix this I needed to create a custom linker script I called linker.x which contains the following:

SECTIONS
{
  . = 0x0;
  .text : { *(.text) }
}

This tells the linker to start the .text section at address 0.

Then I could link the code using:

$ avr-ld -mavr4 -Tlinker.x a.out -o output.o

After linking using the above command all of the .+0's were filled in with their correct values!

The reason for this, is because until the linking stage, as/gcc don't know what else is going to be included in the binary file. It is the linker that takes all the individual object files and combines them into one. So if the linker stage is never run, there is no way to fill in the relative jumps with absolute jumps.

AVR's assembler does the both assembling and linking. But the gnu assembler is more generic and so you need to link separately.

kroylar