Memory Addressing?

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

I have been programming the Atmel micros with assembly language for many years. No problem with assembly. I understand the chips.

 

And I have been programming PCs for more years using VC++. No probelm with that either.

 

But the memories in the Atmell chips are different from those in a PC. You can't write to program memory because it is FLASH. The REGISTER FILE is READ/WRITE memory but not executable,

 

My question is how do you read and write the REGISTER FILE bytes?

 

Can you mix assembly code with C code?

 

I have not been able to find any sample code. Is there any?

 

Bob Macklin

Seattle, Wa

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

Hello, Bob =

 

st and ld, plus in and out, are the assembler instructions you want.

 

Few AVR programmers that I know use concept of REGISTER FILE. There is RAM, ROM, and EEPROM with some of that RAM representing control/data registers.

 

Jim

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

Last Edited: Wed. Mar 14, 2018 - 12:08 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

The AVRlibc manual has two sections regarding ASM & C.

Greg Muth

Portland, OR, US

Xplained/Pro/Mini Boards mostly

 

Make Xmega Great Again!

 

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

cklinbob wrote:
Can you mix assembly code with C code?
Yes for C11 though it's not portable.

Each AVR C toolchain implements such differently.

ISO/IEC 9899 - Revision of the C standard

http://www.open-std.org/JTC1/SC22/WG14/www/projects#9899

WG14 completed the revision of the C standard with ISO/IEC 9899:2011, dubbed C11. A late draft of C11 as of 2011-04-02 is N1570.

...

(in N1570, page 598, "J.5.10 The asm keyword")

cklinbob wrote:
I have not been able to find any sample code. Is there any?
For AVR GCC, try browsing

Atmel Logo

Microchip

AVR Libc Reference Manual

http://www.microchip.com/webdoc/AVRLibcReferenceManual/index.html

...

http://www.microchip.com/webdoc/AVRLibcReferenceManual/assembler.html

http://www.microchip.com/webdoc/AVRLibcReferenceManual/inline_asm.html

...

 

"Dare to be naïve." - Buckminster Fuller

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

My question is how do you read and write the REGISTER FILE bytes?

Not sure what you mean?

 

The register file is another name for the 32 general purpose registers r0 through r31.  On some reduced core devices (like the t4/5/9/10) there are only the 16 registers r16 through r31.

 

Some of those registers have special functions in addition to their role as GP registers.  For instance, r26:25 is the X pointer, r28:27 is the Y pointer, etc, and some instructions apply only to a subset of GP registers.

 

Some (but not all) devices map the GP register into memory, so that they can be read/written with the same instructions used to read/write SRAM.  Is this what you mean?

 

Ultimately, any instructions which takes but does not alter the contents of a GP reg 'reads' that GP reg, and any instructions which alter the contents of a GP reg 'writes' that GP reg.  As such:

mov r16, r18

... reads r18, and writes r16.

 

It seems an odd question from someone who has:

been programming the Atmel micros with assembly language for many years. No problem with assembly. I understand the chips.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

Wonder which AVR you are talking about? There are different memory layouts in some models but a typical one (the ubiquitous 328P at the heart of Arduino) has this:

 

This first diagram is the layout of the flash. This is where the program you write is executed from and you can also store (usually permanent) data here and read it with LPM (Load Program Memory). There is a (limited) possibility to write to it from running code too. You do that with SPM (Self Program Memory). Apart from EEPROM the other main memory area is the RAM/IO:

As you'll see this "map" not only exposes the contents of the peripheral (IO) registers and the SRAm but even the 32 registers of the AVR. You can read write this entire area using LDS/STS/LD/ST but to speed things up there are other opcodes that can access limited ranges of it. The bit from 0x0020 to 0x005F can be accessed by IN  and OUT too. Within that range the first half (0x0020..0x003F) can also be accessed for single bit setting/reading with SBI/CBI/SBIC/SBIS/etc.

 

As for accessing the register file you can set R13 with something like:

LDI R16,123 ; load the value into some register
STS 13, R16 ; store that in memory location 13 (which just happens to be R13 too)

but you might as well just have used (in this case):

LDI R13, 123

The real reason you might use the fact that the registers appear in the memory map is more like:

    CLR R26
    CLR R27 ; make 'X' point to location 0
    LDI R16, 123
    LDI R17, 10
loop:
    ST X+, R16
    INC R16
    DEC R17
    BRNE loop

That will put 123 in R0, 124 in R1, 125 in R2, 126 in R3 and so on. Obviously in this if I had used "LDI R17, 20" I could be in for some real "fun" because at some stage X+ would increment to actually make a write to R16 then R17 and the loop would not stop after a count of just 20 - dire consequences!!

 

BTW if you are talking about the transition to C why does ANY of this matter. You write:

char buffer[10];

int main(void) {
    uint8_t n;
    for (n = 0; n < 10; n++) {
        buffer[n] = n + 123;
    }
}

and the C compiler generates:

00000090 <main>:
#include <avr/io.h>

char buffer[10];

int main(void) {
  90:   e0 e0           ldi     r30, 0x00       ; 0
  92:   f1 e0           ldi     r31, 0x01       ; 1
  94:   2a e0           ldi     r18, 0x0A       ; 10
  96:   31 e0           ldi     r19, 0x01       ; 1
  98:   8b e7           ldi     r24, 0x7B       ; 123
    uint8_t n;
    for (n = 0; n < 10; n++) {
        buffer[n] = n + 123;
  9a:   81 93           st      Z+, r24
  9c:   8f 5f           subi    r24, 0xFF       ; 255

char buffer[10];

int main(void) {
    uint8_t n;
    for (n = 0; n < 10; n++) {
  9e:   e2 17           cp      r30, r18
  a0:   f3 07           cpc     r31, r19
  a2:   d9 f7           brne    .-10            ; 0x9a <main+0xa>
        buffer[n] = n + 123;
    }
}

I couldn't have guessed but the compiler chose to use Z+ to do the indexing into the buffer[] location (my example used X+). It's also using other registers for things like the 123.

 

It's because the compiler "takes care" of all this that you don't have to.

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

On original AVR's the 32 registers are placed in RAM addr. 0-31.

 

Unfortunately newer chips don't have that option :(  

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

cklinbob wrote:
Can you mix assembly code with C code?

gchapman wrote:
Yes for C11 though it's not portable.

Not just C11.

 

The whole point of a Linker in the tool chain is that it links together object files - it neither knows nor cares what source language was used to originate those object files.

 

Each AVR C toolchain implements such differently.

Not just AVR toolchains - this is true for any toolchain.

 

The particular 'C' (or any other language) compiler in question will implement its own call/return conventions, data representations, etc -sometimes known as the "ABI" or "Application Binary Interface"

 

https://en.wikipedia.org/wiki/Ap...

 

if you want to write assembler routines to interface with 'C', then you must observe the ABI.

 

For AVR-GCC, see: https://gcc.gnu.org/wiki/avr-gcc

See also: http://nongnu.org/avr-libc/

 

The easiest way to do this is to write a "skeleton" in 'C' to start you off, and then take the compiler-generated assembled from that as your starting point.

 

 

EDIT

 

Actually, there are 2 ways to mix 'C' & assembler.

 

  1. By writing separate assembler & 'C' source modules, and linking them together - as described above
    (also applicable to mixing other languages)
     
  2. By using "inline" or "embedded" assembler within the 'C' source files.
    I think that's what gchapman  was actually thinking of?

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Wed. Mar 14, 2018 - 09:32 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

cklinbob wrote:
the (sic) Atmel micros

Note that Atmel makes several entirely different ranges of micros: AVR, 8051, ARM ...

 

But the memories in the Atmell chips are different from those in a PC. You can't write to program memory because it is FLASH. The REGISTER FILE is READ/WRITE memory but not executable,

Actually, that's not just Atmel chips; that is typical of microcontrollers of  all types & makes - especially when compared to PCs.

 

These things are usually handled by proprietary language extensions in the compilers targetting these processors.

 

For details of these proprietary language extensions, you need to study the documentation for the particular compiler in question.

You will also need to study that documentation for details of the things which are stated by the 'C' standard to be  implementation-defined.

 

This is why it is particularly important to state what compiler you're using!

 

As noted above, 

For AVR-GCC, see: https://gcc.gnu.org/wiki/avr-gcc

See also: http://nongnu.org/avr-libc/

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Is there any explanation of how the C compiler uses the data ram? 

 

What ram is available to the user and what is used by the compiler.

 

 

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

what should a compiler you RAM for? (it has nothing to hide!)

 

It will have a model for where to put your things, and how to handle the stack.

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

There must be some dusted over copy of  "Inline asm cookbook" for AVR's somewhere...

https://duckduckgo.com/html?q=avr+inline+assembler+cookbook

 

Aren't the registers accesible in the low 0x20 bytes of IO memory space.

Wasn't that why that offset was inserted in the first place?

 

I have never felt a need nor even curiosity to know such things in detail. I just let the compiler handle such low level details.

Sometimes I peek into LSS files to judge the quality of the ASM spit out by the compiler, and that's about it.

 

Paul van der Hoeven.
Bunch of old projects with AVR's:
http://www.hoevendesign.com

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

The answer to that is no difference for a microcontroller than for a PC

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:
I think that's what gchapman  was actually thinking of?
yes

 

"Dare to be naïve." - Buckminster Fuller

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

I've been programming the AVR8 chips with Assembly Language for over 15 years and I am perfectly comfotable with that.

 

But I have come to a point where I need to do 32 bit and 64 bit math. I thought maybe I should try C and use the math library.

 

In assembly language I have absolute control of where items are in the data ram.

 

So I want to try and learn how to use C on these chips.

 

Bob Macklin

Seattle, Wa

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

cklinbob wrote:
I've been programming the AVR8 chips with Assembly Language for over 15 years and I am perfectly comfotable with that.

So you should understand the memory layout as shown, for example, in #6 - and that the Registers just appear as everyday RAM locations ... ?

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Aren't the registers accesible in the low 0x20 bytes of IO memory space.

Wasn't that why that offset was inserted in the first place?

GP registers are not mapped into I/O space.  Both the GP registers and the (low) I/O registers are mapped into SRAM space.

 

So I want to try and learn how to use C on these chips.

Then forget about the 'register file'.  The compiler has control over all of them, and allocates them as needed.  If you want to reserve some of them for use by the asm part of you project, it can be done, but it is fraught with pitfalls, and rarely necessary.  Examine the ABI and calling convention of your toolchain to understand how the GP registers are used by the compiler, and how you can write your asm code to coexist with it.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

joeymorin wrote:
If you want to reserve some of them for use by the asm part of you project, it can be done, but it is fraught with pitfalls, and rarely necessary.  

The Linker is the thing which pulls everything together, and assigns memory locations - so that is the "proper" place to specify any specific memory mappings ...

 

EDIT

 

See #20, below.

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Wed. Mar 14, 2018 - 04:51 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

cklinbob wrote:
But I have come to a point where I need to do 32 bit and 64 bit math.
Fixed-point arithmetic?

If yes that's in later model AVR GCC.

https://gcc.gnu.org/wiki/avr-gcc#Fixed-Point_Support

TR 18037: Embedded C

http://www.open-std.org/JTC1/SC22/WG14/www/projects#18037

 

"Dare to be naïve." - Buckminster Fuller

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

The Linker is the thing which pulls everything together, and assigns memory locations - so that is the "proper" place to specify any specific memory mappings ...

Andy, I was not referring to SRAM, but to register variables.  That is handled by the compiler first.  The linker is not at all concerned with GP register allocation:

Then forget about the 'register file'.  The compiler has control over all of them, and allocates them as needed.  If you want to reserve some of them for use by the asm part of you project, it can be done...

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

joeymorin wrote:
I was not referring to SRAM, but to register variables.

Ah, I see.

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

cklinbob wrote:
I have come to a point where I need to do 32 bit and 64 bit math. I thought maybe I should try C and use the math library.

For integers, AVR-GCC gives you:

long       my_32_bit_value;  // 4 bytes; 32 bits

long long  my_64_bit_value;  // 8 bytes; 64 bits

See: https://gcc.gnu.org/wiki/avr-gcc#Type_Layout

 

So going maths on them is simply a matter of using the standard arithmetic operators.

 

Of course, if you want specfic sizes, then you should use the specific-size types from stdint.h.

 

There are also 24-bit integers: https://gcc.gnu.org/wiki/avr-gcc#Types

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

A lot of your questions require you to first identify your C compiler.

 

If we make the assumption that it is avr-gcc (the one "built in" to AS7) then your question about how the compiler lays things out in RAM is explained in this page of the user manual:

 

http://nongnu.org/avr-libc/user-...

 

I always think a picture is worth 1,000 words and this diagram says it all really:

 

malloc-std.png

 

As for:

cklinbob wrote:
In assembly language I have absolute control of where items are in the data ram.

if it is avr-gcc and you REALLY want to take control over where things are placed then:

C:\SysGCC\avr\bin>type avr.c
#include <avr/io.h>

__attribute__((section(".myram"))) int somevar;

int main(void) {
                somevar = 3729;
}

C:\SysGCC\avr\bin>avr-gcc -mmcu=atmega16 -g -Os -Wl,-section-start=.myram=0x801234 avr.c -o avr.elf

C:\SysGCC\avr\bin>avr-objdump -S avr.elf | tail -n 20
#include <avr/io.h>

__attribute__((section(".myram"))) int somevar;

int main(void) {
                somevar = 3729;
  6c:   81 e9           ldi     r24, 0x91       ; 145
  6e:   9e e0           ldi     r25, 0x0E       ; 14
  70:   90 93 35 12     sts     0x1235, r25
  74:   80 93 34 12     sts     0x1234, r24
}
  78:   80 e0           ldi     r24, 0x00       ; 0
  7a:   90 e0           ldi     r25, 0x00       ; 0
  7c:   08 95           ret

0000007e <_exit>:
  7e:   f8 94           cli

00000080 <__stop_program>:
  80:   ff cf           rjmp    .-2             ; 0x80 <__stop_program>

Now I have no idea why you would want to do this but as you can see from the code I have succeeded in locating a variable called "somevar" at location 0x1234 in RAM. But as soon as start messing with this stuff manually you risk bumping into location decisions the C compiler and linker have already made. Suppose I did this:

C:\SysGCC\avr\bin>type avr.c
#include <avr/io.h>

__attribute__((section(".myram"))) int somevar;
char big_buff[100];

int main(void) {
                somevar = 3729;
}

C:\SysGCC\avr\bin>avr-gcc -mmcu=atmega16 -g -Os -Wl,-section-start=.myram=0x800066 avr.c -o avr.elf

C:\SysGCC\avr\bin>avr-objdump -S avr.elf | tail -n 20

__attribute__((section(".myram"))) int somevar;
char big_buff[100];

int main(void) {
                somevar = 3729;
  7c:   81 e9           ldi     r24, 0x91       ; 145
  7e:   9e e0           ldi     r25, 0x0E       ; 14
  80:   90 93 67 00     sts     0x0067, r25
  84:   80 93 66 00     sts     0x0066, r24
}
  88:   80 e0           ldi     r24, 0x00       ; 0
  8a:   90 e0           ldi     r25, 0x00       ; 0
  8c:   08 95           ret

0000008e <_exit>:
  8e:   f8 94           cli

00000090 <__stop_program>:
  90:   ff cf           rjmp    .-2             ; 0x90 <__stop_program>

I've now placed "somevar" at location 0x66/0x67 in RAM but wait a minute. If I ask for a map file it says:

 *(.bss*)
 *(COMMON)
 COMMON         0x00800060       0x64 C:\Users\someIDorother\AppData\Local\Temp\ccmdokUU.o
                0x00800060                big_buff
                0x008000c4                PROVIDE (__bss_end, .)

That's telling me that the linker already decided to place "big_buff[]" at locations 0x0060 to 0x00C3 so now, because I took manual control I've put my manually located variable "on top" of something that is already being used.

 

When you wrote code in C on a PC did you ever try to locate any data withing it at a fixed memory address? If not why do you think C on an AVR is any different?

 

Part of the reason you use C is that the compiler/linker take this kind of stuff "off your hands". As you say, when you wrote Asm you had to consider the position of every item in memory. But in C that's all decided for you.

 

As I just showed using __attrinute__((section(".name))) and then later -Wl,-section-start=.name=<addr> you can manually position things (both flash and RAM based stuff) but it's very unusual and very dangerous.

 

Oh and if you are wondering about the 0x800000 offsets peppered all over what I just showed you that is because an AVR is "Harvard" but the GCC compiler is "Von Neumann" so there has to be an offset to say "this is flash" (0 based), "this is RAM" (0x800000 based), "this is EEPROM" (0x810000 based) and so on.

Last Edited: Wed. Mar 14, 2018 - 06:07 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Edit: Somehow I overlooked OP's "years of experience in VC++"  which makes the rest of this post a lot less relevant for this thread.

----------------------

Once you are getting a bit familiar with C you will see there will hardly be any use for the very fine grained controll that is mandatory for writing in ASM.

A C programmer (usually ) just don't cares in which registers his variables are. He completely trusts the compiler handles all those details for him.

Often the programmer does not even know if a variable is in ram or not. Especially when optimisation is turned on the compiler may well decide that a certain variable does not even exist in RAM at all, but is only loaded into a register.

 

It can easily even go a step further. The Compiler optimisations may be such that variables declared do not even exist anywhere in the generated asm code any more.

This also does not matter. The C source code is an absraction, and the main purpose of that abstraction is to make it clear to the programmer (and maintainer) of the source code what sort of thing is supposed to happan and in what order.

 

Sometimes the compiler is a bit too enthuisiastic to the naive programmers viewpoint.

If you write a delay loop in asm, you have a delay loop.

If you write a delay loop in C and you do nothing in that loop, then the compiler may well decide that your loop does nothing and completely remove that loop.

The C compiler is also not very smart. It is for example not smart enough to know the concepts of interrupts, where "normal" program flow is, well, interrupted.

In these cases the "volatile" keyword comes in. It basically tells the compiler it can not keep a copy of that variable in an internal register, but it has to load it each time it needs it from RAM, because it could change in unexpected ways the compiler has no knowledge of.

 

You seem to be wanting to translate an ASM program line for line to C. Don't do that. Turn it around.

Go get a book about C, or take info from some online courses or websites, and forget about ASM for a while.

 

Then after you get the hang of the basic ideas behind writing in C you can study the .LSS output of the compiler and judge the quality of the ASM code that GCC generates as an intermediate format.

 

But I stronly suggest to first write some programs in C only before even attempting to mix C and ASM together in a single program.

Mixing those together should really only come after having some knowledge of both languages separately.

 

One of the fun things in C is ist's portability.

For example in the link below I wrote a little C program as an example, and it runs from the command line on my PC.

In C there are ways to "reroute" standard functions such as printf() to for example use a serial port or a HD44780 character LCD.

https://www.avrfreaks.net/comment/2421856#comment-2421856

In the whole example there no single mention of registers, or RAM variables or anything on that level. There just is no need for it in C.

This is a real fundamental difference between C and ASM.

 

And if you like ASM you can dive into linker scripts and the C startup code later.

But I emphasize LATER here. First write some pure C programs to get an idea of the way it is supposed to work.

Paul van der Hoeven.
Bunch of old projects with AVR's:
http://www.hoevendesign.com

Last Edited: Wed. Mar 14, 2018 - 06:34 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you, everyone, for the n+1 version of "assembler vs c". While each of these is a bit of a struggle, each is, to me, quite illuminating. I learn a bit more, each time, about what goes on under the hood. Cliff's posting, and Paul's posting (#23 & #24) have been particularly  illuminating. 

 

Yes, it takes work to present these arguments. But, each time, it increases our general knowledge level. Thanks, for that!

 

Jim

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

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

cklinbob wrote:
I have been programming PCs for more years using VC++.

 

So none of what Paulvdh wrote in his excellent post #24 should come as a surprise?

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ka7ehk wrote:
Few AVR programmers that I know use concept of REGISTER FILE.

Agreed - But every PIC programmer certainly does. A new job this year requires that I join the dark side and become one of them. (Thankfully using PIC24 & PIC32 devices which are both proper grown-up micros).

 

The historic PIC term REGISTER FILE is used for the unified address space that contains both SFR and SRAM spaces we are familiar with on AVR. In the world of PIC, SRAM locations are/were called "registers". Low addresses can be accessed directly but higher addresses must be accessed through a "File Select Register" (FSR) and  associated "Indirect File Register" (INDF)

 

The term is actually still used in the PIC24 datasheet for reasons of backward compatibility with older generation PICs.

 

Hopefully this provides a bit of background to where the term originated and readers can re-read those posts where AVR CPU registers are mentioned, now with a different context.

 

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

If you have some ASM code where some registers are used for often used things, you can declare some of the C variables to be placed in dedicated registers. 

Since this is none standard in C it will be different from compiler to compiler.

in CV it's easy.

with GCC you have to both declare the variable and tell the compiler not to use that for other things.

 

add GCC syntax:

register unsigned char counter asm("r3");

from here :

https://www.microchip.com/webdoc...

 

 

Last Edited: Thu. Mar 15, 2018 - 08:48 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

all true, but

joeymorin wrote:
fraught with pitfalls, and rarely necessary.  Examine the ABI and calling convention of your toolchain to understand how the GP registers are used by the compiler, and how you can write your asm code to coexist with it.

 

If you're going to have C in your project, then I think it makes sense to make C the "master" - and, as joeymorin said, have your ASM fit-in with it.

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My question is how do you read and write the REGISTER FILE bytes?

 So... no one has said yet....

 

In AVR C implementations, you usually write the register files ("IO registers" in AVR-speak) by name:
 

    PORTB = 0;         // set all of portb to 0
    PORTA |= 1<<5; // set bit 5 of porta to 1
    DDRL = 0xFF;     // set all of port L to outputs, via its DDR

 

Atmel provides include files that map all those names to their memory addresses, and then the C compiler optimizer is typically good enough to know that the first line can be done with an LDI/OUT instruction sequence, the second with a single SBI instruction, and the last is going to need a STS instruction.  There is no need to mix assembler with your C code for such "ordinary" purposes.  (we can argue separately about when it IS useful to add assembly, of course, and it usually IS fun and enlightening...)

 

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

I think the OP's use of "REGISTER FILE" means the CPU registers - not the IO registers?

 

aka SFRs = Special Function Registers.

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

+1

OP write ASM code, where a register is r0-r31

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

In which case:
.
uint8_t * p =(uint8_t *) 0x0013;
*p = 0xA5;
.
HOWEVER that just trashed R19! How do you know if the compiler was already holding something important in R19?
.
While you can use "register uint8_t foo asm(" r19") " to put a variable in a selected register you seriously inhibit the compiler's ability to optimize.

Last Edited: Thu. Mar 15, 2018 - 10:16 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The code you show will only work on org. AVR's not XMEGA, xtiny's 16 register AVR's!

 

for r2-r15 the register var. make sense.

 

but OP should know that things like 16 bit atomic update are not guaranteed to work in C! (use of atomic  or enable/disable ISR are needed, but it make bulky code )

 

 

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

I wasn't really showing how to do it - I was highlighting that it would be a pretty mad thing to do.

 

The fact is that C compilers are pretty good at writing assembler. Maybe not as good as the true experts like "sparrow2"/"danni"/etc but for most things they do a more than adequate job. This maybe isn't a surprise because the code generation models are written by some of the best AVR Asm experts there are (nothwithstanding the aformentioned!). True there is a "clumsiness" to the auto-code geenration system and that leads to small inefficiencies but the best idea is simply to implement everything you require in C and only if there are some very specifically time critical parts then examine the C the compiler created (even use -save-temps to get it to create .s files for you) and then just use your Asm skils to hand optimize those small parts that are in the critical path.

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

And often forgotten (as with this thread, it seems):

"register uint8_t foo asm(" r19")" is only half of the task (binding a variable to a register).

The other half is to tell the compiler about that with the -ffixed-19 option.

Stefan Ernst

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

I mentioned it in #28 :)

 

And that link actuallu say that r2-r7 should be safe without.

Last Edited: Thu. Mar 15, 2018 - 02:15 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sparrow2 wrote:
I mentioned it in #28 :)
Sorry, I haven't read everything, I simply did a CTRL-F ffixed. ;-)

Stefan Ernst

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

So are you saying that if you are not ffixed you are ff*cked ? ;-)

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

Anyone seen the OP? ;-) ... only made two three posts, including the top post.

 

I wonder if there's a confusion on his(her) part w.r.t. the meaning of 'register file'.  For instance:

 

westfw wrote:

In AVR C implementations, you usually write the register files ("IO registers" in AVR-speak) by name:

... which shows that even seasoned experts might get it wrong:

 

 

 

The moral of the story:  Register File <> I/O registers

... but maybe the OP >>was<< referring to I/O registers...?

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

Last Edited: Fri. Mar 16, 2018 - 06:40 PM