avr-as and word addresses

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

Hi,

 

I'm working with avr-as and trying to load the word address of a function into a register pair.  I am getting the byte address.  Does anyone know the syntax to do this?

 

Below is my function "spin".   Say it's byte address is 0x240.   Then I want to load 0x120 into r23:r22.  The code below is loading 0x240 into r23:r22.

 

	.section .text
	
	.type spin,function
spin:	nop
	rjmp spin
	
	...
	ldi r22,lo8(spin)
	ldi r23,hi8(spin)

 

This topic has a solution.
Last Edited: Sun. Apr 14, 2019 - 11:35 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

One right shift ought to do it. Since more than one byte is involved, you will have to put the carry from the high byte into the msbit of the low byte, which means shifting the low byte first.

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I found it in the libc manual.  It's pm():

 

	
	.type spin,function
spin:	nop
	rjmp spin
	
	...
	ldi r22,lo8(pm(spin))
	ldi r23,hi8(pm(spin))

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

And thanks for the input Jim.  I was looking for compile-time /2 since it's a constant.

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

MattRW wrote:
I found it in the libc manual. 
While it may be in the libc manual I'd say the more definitive description is the avr-as manual:

 

https://sourceware.org/binutils/docs/as/AVR_002dDependent.html#AVR_002dDependent

 

specifically:

 

https://sourceware.org/binutils/docs/as/AVR_002dModifiers.html#AVR_002dModifiers

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

clawson wrote:

MattRW wrote:
I found it in the libc manual. 
While it may be in the libc manual I'd say the more definitive description is the avr-as manual:

 

https://sourceware.org/binutils/docs/as/AVR_002dDependent.html#AVR_002dDependent

 

specifically:

 

https://sourceware.org/binutils/docs/as/AVR_002dModifiers.html#AVR_002dModifiers

 

I looked in the as manual first..  The pm() operator is not mentioned in the as manual. but I'd guess lo8(pm()) == pm_lo8().

The descriptions of pm_lo8 and lo8 don't indicate the distinction.

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

MattRW wrote:
Say it's byte address is 0x240.   Then I want to load 0x120 into r23:r22. 

Hmmm--us common people that use the Atmel assembler look at it with different colored glasses.

                 ;GLOBAL VARIABLES INITIALIZATION
0003ed e8ec      	LDI  R30,LOW(__GLOBAL_INI_TBL*2)
0003ee e0f7      	LDI  R31,HIGH(__GLOBAL_INI_TBL*2)
                 __GLOBAL_INI_NEXT:
0003ef 9185      	LPM  R24,Z+
0003f0 9195      	LPM  R25,Z+

MattRW wrote:
I was looking for compile-time /2 since it's a constant.

...so that was my first thought, /2 instead of *2.  But inquiring minds want to know:  What are you going to do with the word address once loaded?  Show those next lines...

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

I am writing a hard real-time tasking utility called "octos".   Features:

1) 8 tasks, task 7 is reserved as "idle task" which will spin or sleep (for simplicity I hardcode oct_spin below)

2) usable task ids are 0..6; TASK0 is highest priority, TASK6 lowest

2) gcc-compiled main task initializes via oct_os_init(task-id) to register which task id

 

	.type oct_spin,function
oct_spin:
0:	rjmp 0b

	;; void oct_os_init(uint8_t id)
	.type oct_os_init,function
oct_os_init:
	;; task id in r24
	;; callee, so save r28,r29
	push r29
	push r28
	;; register idle task
	push r24		; save task-id arg
	ldi r24,0x80		; r24 <= TASK7 id
	ldi r23,pm_hi8(oct_spin)
	ldi r22,pm_lo8(oct_spin)
	ldi r21,hi8(idletop)
	ldi r20,lo8(idletop)
	ldi r19,hi8(idletop-idlestk)
	ldi r18,lo8(idletop-idlestk)
	rcall oct_register_task
	...
	ret

	;; void oct_register_task(uint8_t id, void (*fn)(void),
	;;                        uint8_t *sp, uint16_t sz)
	;; id: task id (r24)
	;; fn: function (r23:r22)
	;; sp: stack end pointer (r21:r20)
	;; sz: stack size (r19:r18)
	.type oct_register_task,function
oct_register_task:
	...
 	ret

EDIT: currently octos requries ~400 bytes flash, 40 bytes sram (which includes stack for only the idle task)

Last Edited: Fri. Apr 26, 2019 - 01:55 AM