[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Fwd: Re: [avr-gcc-list] in-line assembler]
From: |
Robert von Knobloch |
Subject: |
Re: [Fwd: Re: [avr-gcc-list] in-line assembler] |
Date: |
Tue, 11 Aug 2009 13:56:29 +0200 |
User-agent: |
Thunderbird 1.5.0.14 (X11/20060911) |
Many thanks for your help Wouter.
No, it's not a pointer to pointer, just:
<load Y-register with address>
< load temp with what is addressed by Y>
<store temp to my return variable>
which is done here :
"lds r29, ram_address + 1\n\t" // Load high byte of Y
"lds r28, ram_address\n\t" // Load low byte of Y
"ld __tmp_reg__, Y\n\t" // Fet value at Y into __tmp_reg__
"sts rambyte, __tmp_reg__\n\t" // Store __tmp_reg__ into named
variable 'rambyte'.
// It's this last line that I have not
yet achieved using the 'proper' syntax.
but it is wrong.
I seem to have solved my immediate problem but still don't quite understand how
to save __tmp_reg__ to a named variable.
Just for info, the much simplified:
uint8_t get_ram_byte(uint16_t ram_address)
{
uint8_t byte;
asm ("ld %0, %a1" : "=&r" (byte) : "e" (ram_address));
return byte;
}
works fine (I don't really need the temp storage as %0 gets loaded from
the Y-reg directly.
The declaration and usage of 'byte' is completely discarded by the
compiler, it just chooses R24 as %0 and uses that as its uint8_t return:
00000666 <get_ram_byte>:
uint8_t get_ram_byte(uint16_t ram_address)
{
uint8_t byte;
asm ("ld %0, %a1" : "=&r" (byte) : "e" (ram_address));
666: fc 01 movw r30, r24
668: 80 81 ld r24, Z
return byte;
}
66a: 08 95 ret
Anyway, many thanks for your help Wouter, I'll try to figure out storage
later.
Robert.
Wouter van Gulik wrote:
> Robert von Knobloch schreef:
>
>> Hi Wouter,
>>
>> thanks for responding.
>> This is not quite what I want, but your comment about the sts is
>> interesting.
>> I want to achieve this:
>>
>> uint8_t rambyte;
>> uint16_t ram_address;
>>
>> void get_ram_byte(void)
>> {
>> asm ("push R28\n\t"
>> "push R29\n\t"
>>
>> "lds r29, ram_address + 1\n\t"
>> "lds r28, ram_address\n\t"
>> "ld __tmp_reg__, Y\n\t"
>> "sts rambyte, __tmp_reg__\n\t"
>>
>> "pop R29\n\t"
>> "pop R28"::);
>> }
>>
>> Which works but completely ignores the inline-assembler stuff which
>> would do automatic register saving etc.
>> I want to pass a uint16_t address as the argument and get a uint8-t byte
>> returned (which is the contents of the address in ram.
>>
>
> So you want a pointer to a pointer?
> So in C it would be something like this:
>
> get_ram_byte(char **pp)
> {
> char c;
> char *p = *pp;
> c = *p;
> *p = c;
> return c;
> }
>
>
>> Here is the sts that I want to achieve - namely storing the __tmp_reg__
>> contents into the variable rambyte. Of course this should become the
>> return value (must I store this in a variable first or can the compiler
>> know to return this in whatever the usual register is for a uint8_t () ?.
>>
>
> You must use a C variable to return the value. Of course you could just
> tell it to store it to R24 (which is the return register for an
> uint8_t). But this might will lead to compile warnings and faulty code
> when GCC decides to inline.
> So don't use __tmp_reg__ but replace it with the construction from my
> previous mail.
>
>
>> Btw your example compiled OK but did not assemble.
>>
>> Robert
>>
>> Hi,
>>
>> I don't know what you intended to do but I guess this is more like it
>> (read the value and write it back):
>> I personally prefer the %[] construction.
>>
>> uint8_t get_ram_byte(uint16_t ram_address)
>> {
>> uint8_t byte;
>>
>> asm ("ld %[reg] , %[adr]" "\n\t"
>> "sts %[adr] , %[reg]" "\n\t"
>> : [reg] "=&r" (byte)
>> : [adr] "e" (ram_address));
>> return byte;
>> }
>>
>> You're construction of "sts %0, __tmp_reg__" is not correct. GCC is
>> trying to feed sts r24 as first argument, which is invalid.
>> You are feeding him the uninitialized variable 'byte'. Which is also
>> allocate to R24.
>>
>> HTH,
>>
>> Wouter
>>
>>
>> Robert von Knobloch schreef:
>>
>>> Hello,
>>> I've been trying to decipher the intricacies of in-line assembler (using
>>> the Inline Assembler Cookbook as my guide).
>>>
>>> I have a very simple application that I cannot seem to realise.
>>>
>>> I want a C function that will return the contents of the RAM address
>>> that I give it as argument.
>>>
>>> My assembler-based function looks like this:
>>>
>>> file is hex.c
>>> =====
>>> uint8_t get_ram_byte(uint16_t ram_address)
>>> {
>>> uint8_t byte;
>>>
>>> asm ("ld __tmp_reg__, %a1" "\n\t"
>>> "sts %0, __tmp_reg__" "\n\t"
>>> : "=&r" (byte) : "e" (ram_address));
>>> return byte;
>>> }
>>>
>>> and is called from
>>>
>>> rambyte = get_ram_byte(i );
>>> u_hex8out(rambyte); // Print byte as 8-bit hex.
>>>
>>> Trying to compile this results in "~/Monitor/hex.c:5: undefined
>>> reference to `r24' "
>>> If I comment out the line "sts %0, __tmp_reg__" "\n\t" then it
>>> compiles and I see that the parameter is passed in R24,25, copied to
>>> R30,31[Z] and the value is read into R0 [__tmp_reg__].
>>> I cannot see what is wrong with the sts command or why R24 is mentioned.
>>>
>>> Can anybody help me ?
>>>
>>> Many thanks,
>>>
>>> Robert von Knobloch.
>>>
>>>
>>>
>>> _______________________________________________
>>> AVR-GCC-list mailing list
>>> address@hidden
>>> http://lists.nongnu.org/mailman/listinfo/avr-gcc-list
>>>
>>
>>
>>
>>
>> _______________________________________________
>> AVR-GCC-list mailing list
>> address@hidden
>> http://lists.nongnu.org/mailman/listinfo/avr-gcc-list
>>
>
>
>
>