Initializing Z pointer in assembly

Discussion in 'Homework Help' started by Sebbe, Dec 27, 2015.

  1. Sebbe

    Thread Starter New Member

    Dec 20, 2015
    8
    0
    Hey, I am learning how to code in assembly to a AtMega32u4 cpu.
    In the example below (from Atmel) the LPM-instruction is demonstrated.
    What I don't get is why it is necessary to shift the bits one step left when it loads the address to the Z-registers.

    <quote>

    ldi ZH, high(Table_1<<1) ; Initialize Z pointer
    ldi ZL, low(Table_1<<1)
    lpm r16, Z ; Load constant from program
    ; memory pointed to by Z (r31:r30)
    ...
    Table_1:
    .dw 0x5876; 0x76 is addresses when ZLSB = 0
    ; 0x58 is addresses when ZLSB = 1
    ...

    </quote>
     
  2. sailorjoe

    Member

    Jun 4, 2013
    361
    63
    Atmel instructions say that program memory is organized as 16 bit words, but the Z pointer is a byte address. So the left shift by one position changes the Z pointer to act like a word address (16 bits) rather than a byte address. OK?
     
    Sebbe likes this.
  3. Sebbe

    Thread Starter New Member

    Dec 20, 2015
    8
    0
    Thanks, I think I understand the purpose but the way it works has me wondering.
    So in the following scenario:

    Table: .dw 0xFFFF ;0b1111111111111111
    .
    .
    LDI ZH, high(Table<<1)
    LDI ZL, low(Table<<1)

    ...this would result in register ZH being given what value exactly?
    And ZL?

    My guess would be
    ZH : 0b11111111
    ZL : 0b11111110
    But if so is the case why is the left shift used twice?
    Left shift, shifts all bits one position to the left, introducing zeroes from the right, correct?
     
    Last edited: Dec 29, 2015
  4. Sebbe

    Thread Starter New Member

    Dec 20, 2015
    8
    0
    I think I understand it now, please correct me if I'm wrong.

    By initiating Z we give each of the two registers (ZL=R30 and ZH=R31) a byte each.
    These two bytes form a 16-bit word address where the first bit (LSB) is a 1 by default. When you then load a register with the value that Z points to (through the address it contains) one has to specify which of the bytes (low or high byte) you want to load to the register because the register has a capacity of 1 byte not 2. The LSB in the address does just that, specifies which byte, if it is the higher byte or the lower byte that should be loaded when the address Z contains is used.

    Example:
    table_1: DB. 0x1A2B
    .
    .
    LDI ZL,LOW(table_1)
    LDI ZL,HIGH(table_1)
    LPM R16,Z ;R16 will now be loaded with 0x1A
    LDI ZL,LOW(table_1 <<1) ;The shiftLeft doesn't change the original address
    LDI ZL,HIGH(table_1 <<1) ;shiftLeft to get same as above since high byte might've changed
    LPM R17,Z ;R17 will now be loaded with 0x2B
     
    Last edited: Dec 29, 2015
  5. Sebbe

    Thread Starter New Member

    Dec 20, 2015
    8
    0
    "The LSB in the address does just that, specifies which byte, if it is the higher byte or the lower byte that should be loaded when the address Z contains is used."

    is used through Z (indirect access).
     
  6. sailorjoe

    Member

    Jun 4, 2013
    361
    63
    I believe you've got it, Sebbe. Understanding the memory architecture of a microcontroller is an important first step in understanding how to write programs for it. This is true even in mainframe programming. Every system is different. If you aren't familiar with these terms already, look up "little endian", "big endian", and Harvard Architecture. Just for fun.
     
    Sebbe likes this.
  7. Sebbe

    Thread Starter New Member

    Dec 20, 2015
    8
    0
    Thanks! Will do that.
     
Loading...