Another asm question (lpm)

Go To Last Post
5 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have C code that looks something like this:

static const PROGMEM byte progdata[6] = {0x55, 0x3E, 0xBB, 0x21, 0x92, 0x02};

static byte testarray[6];

void testpgm()
{
   testarray[0] = pgm_read_byte_near(progdata + 0); 
   testarray[1] = pgm_read_byte_near(progdata + 1); 
   testarray[2] = pgm_read_byte_near(progdata + 2); 
   ...
}

The resulting avr-gcc produced asm looks something like this:

ldi r30,lo8(progdata)
r31,hi8(progdata)
lpm r24, Z
sts testarray,r24
adiw r30,1
lpm r24, Z
sts testarray+1,r24
adiw r30,1
lpm r24, Z
...

I noticed that the address of progdata is copied directly into the Z register, unlike in Atmel asm which multiplies by 2. Based on the brne thread, I assume this is because GAS keeps byte addresses rather than 16 bit word addresses to progmem? But what if the address of progdata was used in an instruction that expected a word address? Does the conversion to word addressing happen on a per instruction basis?

-Brad

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The bottom line is that GCC is 8bit for everything.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

as Cliff said, gcc exposes all addresses as byte addresses to the programmer.

However, in general, it is your responsibility as the programmer ot maintian coherence when moving between byte and word addresses. The branch instructions of the AVR expect word addresses at the low level, and since every instruction is a word in size, or a multiple of a word, it is impossible for an instruction to fall on an odd byte boundary. This in essence gives you twice the addressing range you normally would for the same number of bits.

LPM on the other hand expects a byte address. This is because processing wise the AVR is an 8 bit machine. Ulitmately it is still used as a word address, with the low bit selecting the high or low byte of the addressed word.

Reading up on the architecture of the AVR should make all of this more clear to you.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

glitch wrote:
LPM on the other hand expects a byte address.
Note, also, that icall and ijmp instructions expect a word address. The compiler takes care of this detail for you but if you write assembly language code that uses icall and ijmp you'll find the pm() macro useful to generate a word address.

Don Kinzer
ZBasic Microcontrollers
http://www.zbasic.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Think I got it. If writing/debugging Atmel assembler its the programmers job to convert from word addresses to byte addresses when needed (aka LPM). And if writing/debugging GAS assembler its the programmers job to convert from byte addresses to word addresses when needed (aka BR..). Correct?

-Brad