Atmel assembly language - Page 1
Forum section: electronics / general

author: Roeland_R
author_rank: Regular Contributor
timestamp: October 12, 2015, 06:59:11 pm
content: Hi everybody,A little introduction:In the past (1990-1999) I used to build test equipment for a smal company here in the Netherlands using the Texas tms370 microcontrollers programmed in assembly language. Now for hobby I started programming in assembler the atmega368p microcontroller building little routines first that I can use for my projects. I needed to copy variables from program memory to some of the first 16 registers and found the solution here below. It works fine. Values from Test_Value are copied to cnt3 to cnt0. (r6,r7,r8 and r9). What I don't understand is why I need the <<1 shift to left option to load the address of table Test_Value to index pointers ZH and ZL. Does anyone know?ldi ZH,high(Test_Value<<1)ldi ZL,low(Test_Value<<1)lpm cnt3,Z+ ;lpm cnt2,Z+ ;lpm cnt1,Z+ ;lpm cnt0,Z+ ;Test_Value:; test value 12345678.db 0x00,0xbc,0x61,0x4e

author: bktemp
author_rank: Super Contributor
timestamp: October 12, 2015, 07:03:12 pm
content: The program memory is 16bit wide. Therefore all adresses and labels are beeing counted in words (16bit), but the lpm command needs a byte address, so the word count needs to be multiplied by 2.

author: Roeland_R
author_rank: Regular Contributor
timestamp: October 12, 2015, 07:12:46 pm
content: Quote from: bktemp on October 12, 2015, 07:03:12 pmIn my program, Test_Value address is 00e4. While debugging I see ZH is set to 00, and ZL is set to e4 as expected. I should say it would not be neccesary to shift left one bit to multiply by 2.

author: bktemp
author_rank: Super Contributor
timestamp: October 12, 2015, 07:23:09 pm
content: The debugger shows byte adresses.If you write rjmp Test_Value, then the assembler expects a word address, therefore the assemblers treats all labels as word adresses.

author: Roeland_R
author_rank: Regular Contributor
timestamp: October 12, 2015, 08:17:35 pm
content: Thanks for trying to explain this to me, but I still don't understand the shift to left. A command like low(tablename) should select the lower 8 bits of the word address of the tablename. So why low(tablename<<1) is used. Perhaps I am confused being used to another syntax of the tms370 assembler. That also had 16 bits addressing. I always want to understand the things I program. When it works copying a command it always keeps me puzzeling why it works the way it does. (Please forgive my bad english. It is not my native language)

author: richardman
author_rank: Frequent Contributor
timestamp: October 12, 2015, 08:47:19 pm
content: LOW() does not convert word address to byte address. The LPM and everything else uses WORD address, at least in the Atmel assembler, so you need to explicitly convert it to byte address.

author: Roeland_R
author_rank: Regular Contributor
timestamp: October 13, 2015, 04:58:42 pm
content: So the <<1 is needed only to convert to a byte address?

author: commie
author_rank: Frequent Contributor
timestamp: October 13, 2015, 05:46:50 pm
content: Quote from: Roeland_R on October 13, 2015, 04:58:42 pmThere are two assembler directives in use which are, db(8-bit) and dw(16bit), if you use db for define byte, for your rom table, then you need to shift your 16bit pointer one bit to the left or multiply by 2.

author: Roeland_R
author_rank: Regular Contributor
timestamp: October 13, 2015, 06:34:08 pm
content: Thanks everyone. All clear now.