[dorkbotpdx-blabber] assembler on the arduino?

485 views
Skip to first unread message

Greg Borenstein

unread,
Jan 27, 2008, 3:58:26 PM1/27/08
to dorkbotpd...@music.columbia.edu
Hey y'all,

I was wondering if anyone had any advice for someone who wants to use
the Arduino as a platform for learning Assembler. Are there any good
guides out there for getting started writing and running assembler on
the Arduino? Any truly beginner level texts for writing Assembler in
general?

I'm an upper-intermediate level Arduino programmer with no assembler
experience. Starting tomorrow, I'll be auditing a class at Reed on
language design and threading for the micro-controller environment
that's going to be using the Arduino as a test subject and I wanted to
try to get some of the basics under my belt.

Thanks,

Greg
---
http://grabb.it/users/greg
http://urbanhonking.com/ideasfordozens
http://atduskmusic.com
_______________________________________________
dorkbotpdx-blabber mailing list
dorkbotpd...@dorkbot.org
http://music.columbia.edu/mailman/listinfo/dorkbotpdx-blabber

Paul Stoffregen

unread,
Jan 27, 2008, 4:49:42 PM1/27/08
to A discussion list for dorkbot-pdx (portland, or)
It's really pretty easy, at least to do simple things. If you start
manipulating complex data structures, assembly gets tedious pretty quickly.

I don't have any beginner advise, but here's some chunks of code you
might fine helpful for sending stuff out the serial port.


;initialize uart, transmit only, 115200 baud
init_uart:
ldi r16, (ubrr_value >> 255)
sts UBRR0H, r16
ldi r16, (ubrr_value & 255)
sts UBRR0L, r16
ldi r16, 0
sts UCSR0A, r16
ldi r16, (1<<UCSZ1)|(1<<UCSZ0) ;1 stop bit
;ldi r16, (1<<UCSZ1)|(1<<UCSZ0)|(1<<USBS) ;2 stop bits
sts UCSR0C, r16
ldi r16, (1<<TXEN)
sts UCSR0B, r16
ret

cout:
push r16
cout_wait:
lds r16, UCSR0A
sbrs r16, UDRE
rjmp cout_wait
pop r16
sts UDR0, r16
ret

newline:
push r16
ldi r16, 13
rcall cout
ldi r16, 10
rcall cout
pop r16
ret

phex:
push r16
swap r16
andi r16, 15
subi r16, 10
brcs phex_2
subi r16, 249
phex_2: subi r16, 198
rcall cout
pop r16
p1hex: push r16
andi r16, 15
subi r16, 10
brcs phex_3
subi r16, 249
phex_3: subi r16, 198
rcall cout
pop r16
ret


.macro pstr
rcall pstr_string_addr
.dw (@0 * 2)
.endmacro


;this complex pstr allows the caller to place the string
;address in memory immediately following the call instruction,
;an no register values are modified by this function. No need
;to use LDI instructions to pass the string address in the
;registers, and push/pop instructions before/after the LDI
;and call. This function preserves all register values, gets
;the string address from the next code word after the call,
;and re-writes the return address on the stack so it returns
;properly to the caller's code after the string is printed
pstr_string_addr:
push Zl
push Zh
push r24
push r25
in Zl, spl
in Zh, sph
ldd r25, Z+5 ;grab return address from stack
ldd r24, Z+6
adiw r24, 1
std Z+5, r25 ;inc return address on stack
std Z+6, r24
sbiw r24, 1
lsl r24 ;translate code space addr
rol r25
mov Zl, r24
mov Zh, r25
lpm r24, Z+ ;fetch address of string
lpm r25, Z+
mov Zl, r24
mov Zh, r25
pop r25
pop r24
push r16
pstr_s_loop:
lpm r16, Z+ ;fetch string bytes
tst r16
breq pstr_s_end ;finish if null terminator
rcall cout
rjmp pstr_s_loop
pstr_s_end:
pop r16
pop Zh
pop Zl
ret


;to use this, write something like "pstr my_debug_msg" in your code
;and at the end of all you code, write 'my_debug_msg: .db "My debug
message",0'

Greg Borenstein

unread,
Jan 27, 2008, 10:53:03 PM1/27/08
to A discussion list for dorkbot-pdx (portland, or)
Hey Paul,

Thanks! That looks like it'll be really helpful once I'm up and
running. I guess the first thing I was looking for was some advice on
how to run assembler on the Arduino at all.

Any tips on that? Even if they're really basic, they'll be a place to
get started...

Thanks,

Greg

Donald Delmar Davis

unread,
Jan 28, 2008, 5:53:59 AM1/28/08
to A discussion list for dorkbot-pdx (portland, or)
Somewhere there are a couple of european engineers smacking
themselves repeatedly on the forehead.

The AVR processor was specifically designed to run C and there are
only a few processors left in the current production where assembly
actually makes sense.

(Unless you are Paul and you really,really like assembly. :)

I am interested in hearing about the class and how the arduino (and
the avr) as test subject effects the languages used on it.
(This is based on some extended forays into how badly the processor
is set up for a an on board TIL like forth).

Best of luck.

Greg Borenstein

unread,
Jan 28, 2008, 11:28:51 AM1/28/08
to A discussion list for dorkbot-pdx (portland, or)
Don,

I, of course, realize that assembly is not the most natural way to
program an AVR processor. I'm not going for utility here, but for
education!

And the first step in that quest is to actually be able to run some
assembly on my Arduino. Any tips on that or is just warnings all the
way down? ;)

I'll keep you guys up to date on the Arduino-related bits of the class
as it proceeds.

-- Greg

yiyi

unread,
Jan 28, 2008, 11:57:26 AM1/28/08
to A discussion list for dorkbot-pdx (portland, or)
Perhaps you could just do inline assembly:
http://www.nongnu.org/avr-libc/user-manual/inline_asm.html

Arduino doesn't really allow for you to do straight assembly, without a lot of work arounds. To do straight assembly, it would be much easier to just buy an stk500 and some atmega's.

Arduino is meant to be easy and a one stop shop, so doing weird things like writing assembly isn't going to be as easy as doing it normally, but doing normal things, like writing C, it makes super easy.

Thomas Lockney

unread,
Jan 28, 2008, 12:22:19 PM1/28/08
to A discussion list for dorkbot-pdx (portland, or)
yiyi wrote:
> Arduino doesn't really allow for you to do straight assembly, without
> a lot of work arounds. To do straight assembly, it would be much
> easier to just buy an stk500 and some atmega's.
Yes, but the point is that the class Greg is taking/auditing has (if I
read his original email correctly) already chosen to use the platform
for assembly programming. So clearly someone in an academic position
thinks it's a reasonable choice. Whether we agree is beside the point.

Greg, please correct me if I misread your original message. Also, is
there by any chance a copy of the sylabus for the class available
online? I'm sure plenty of us on this list would be interested in
hearing more about it. If I had known about it, I probably would have
even tried to audit it myself. ;~)

~thomas

Greg Borenstein

unread,
Jan 28, 2008, 12:39:08 PM1/28/08
to A discussion list for dorkbot-pdx (portland, or)
Thomas,

You've got it exactly right. Maybe the prof is planning to use exactly
that C-based method yiyi pointed me, too. I guess I'll find out soon.
I was mostly just trying to get a head start on some of this stuff
since I'm going to be playing catch up not ever having taken a formal
computer science class before. I thought that at least I could be the
guy who knew how to actually run code!

Anyway, Thomas, I can't find the syllabus online (though I might have
better info about that after the first class this afternoon).

In the meantime, this seems to have been the previous version of it:

http://people.reed.edu/~jimfix/442rcx/

And this is the Professor Fix's courses page:

http://people.reed.edu/~jimfix/courses.html

-- Greg

Thomas Lockney

unread,
Jan 28, 2008, 12:49:32 PM1/28/08
to A discussion list for dorkbot-pdx (portland, or)
Greg Borenstein wrote:
> Thomas,
>
> You've got it exactly right. Maybe the prof is planning to use exactly
> that C-based method yiyi pointed me, too. I guess I'll find out soon.
> I was mostly just trying to get a head start on some of this stuff
> since I'm going to be playing catch up not ever having taken a formal
> computer science class before. I thought that at least I could be the
> guy who knew how to actually run code!
>
> Anyway, Thomas, I can't find the syllabus online (though I might have
> better info about that after the first class this afternoon).
>
> In the meantime, this seems to have been the previous version of it:
>
> http://people.reed.edu/~jimfix/442rcx/
Is this it? http://people.reed.edu/~jimfix/442es/

If so, it makes a lot more sense now. Of course, it also looks like a
pretty serious bit of work. You're in for quite a bit of learning
(beyond the classwork, most likely) if you haven't delved into
compilers, programming language theory, etc. Sounds like fun!

Greg Borenstein

unread,
Jan 28, 2008, 1:08:51 PM1/28/08
to A discussion list for dorkbot-pdx (portland, or)
That's the one.

-- Greg

Ben Bleything

unread,
Jan 28, 2008, 1:19:36 PM1/28/08
to A discussion list for dorkbot-pdx (portland, or)
On Mon, Jan 28, 2008, Greg Borenstein wrote:
> You've got it exactly right. Maybe the prof is planning to use exactly
> that C-based method yiyi pointed me, too. I guess I'll find out soon.
> I was mostly just trying to get a head start on some of this stuff
> since I'm going to be playing catch up not ever having taken a formal
> computer science class before. I thought that at least I could be the
> guy who knew how to actually run code!

If you're just looking for assembler principles, I'd look at a PIC
instead. It looks like the class is going to cover how to do everything
you want to do on the AVR/Arduino, so I wouldn't stress yourself trying
to figure it out ahead of time.

The PIC is a (somewhat) similar uC to the AVR, is way cheap and
programmers and really simple and cheap. In fact, you can just borrow
my programmer and I'll give you some PICs. You'll be able to get the
feel of assembly and still be working on a uC.

Alternately, JVM assembly is pretty easy and interesting, and it's very
accessable.

These options will only give you the "feel" of assembler, and you'll
have to rely on the class to show you how it works on the target
platform.

Finally, you can use an AVR but you'll need a programmer... there are
some low-cost AVR programmers available, but an STK-500 will pay off in
the long term.

Ben

Greg Borenstein

unread,
Jan 28, 2008, 1:47:07 PM1/28/08
to A discussion list for dorkbot-pdx (portland, or)
Ben,

What you're saying definitely makes sense. And I'd love to take you up
on your offer. When can I come grab them from you?

Also, if you've got some assembler experience, can I buy you a beer
and get a basic tutorial from you some time with the gear?

Thanks!

-- Greg

Ben Bleything

unread,
Jan 28, 2008, 1:53:28 PM1/28/08
to A discussion list for dorkbot-pdx (portland, or)
On Mon, Jan 28, 2008, Greg Borenstein wrote:
> What you're saying definitely makes sense. And I'd love to take you up
> on your offer. When can I come grab them from you?

Not today, since they're at home, but any other day if you warn me :)

> Also, if you've got some assembler experience, can I buy you a beer
> and get a basic tutorial from you some time with the gear?

Sure! I can try, anyway. I'm an amateur, but I've at least taken the
OSU equivalent of the class you're auditing ;)

Paul Stoffregen

unread,
Jan 28, 2008, 2:06:29 PM1/28/08
to A discussion list for dorkbot-pdx (portland, or)
Ultimately, your assembler is going to produce a .hex file which is an
ascii encoded copy of the raw data that needs to be programmed into the
MEGA168 chip. All you need to do is write that code into the MEGA168
chip, run it, and have some way to observe what it's doing so you can
debug it (unless you never make any mistakes!)

There are 2 ways to program code into the MEGA168 chip.

#1: if the chip already has a bootloader programmed in, you can cause
the bootloader to run and it will receive a download of code and write
it into the chip (except for the portion which already has the
bootloader, of course). This is how the arduino is normally used.

#2: by connecting to a few pins, you can directly program code into any
portion of the chip. This is the only way to initially write the
bootloader. To do this, you need to buy or build hardware that
manipulates the special programming pins. For example:
http://www.arduino.cc/en/Hacking/ParallelProgrammer This is the way I
have always programmed the Atmel AVR chips, though my custom-build
hardware is quite different, the idea is the same.

There is actually another way, pretty much the same as #2, but many more
pins are used for a small speed increase. It's pretty much only used to
program the chips in high volume production.

Usually, to observe what your code is doing, you'll send data via the
UART to your PC serial port. You can use the arduino software or any
terminal emulator to view it. You can also toggle output pins, which
gives a lot less info but also takes a lot less time. There are also
expensive in-circuit emulator products that let for more or less
directly observe stuff, but if you have the arduino, you're probably not
going to buy one of those.


Also, there are 2 different approaches to assembly language.

Most commonly, people opt to write mostly in C and code tiny pieces in
assembly. C is a lot less work than assembly, so the reasoning goes
that you can do everything "easily" in C that isn't speed critical, then
only do the "hard work" on a few little sections. This is true,
however, the compiler will impose a lot of constraints on your assembly
code. Entry and exit from functions requires parameter passing using
pre-defined registers (and the stack if more params), most other
registers have to be saved if you use them, and so on. Your freedom to
allocate the registers is severely constrained. While you don't have to
write very much assembly this way, the bits you do write have many rules
to follow. That makes it more difficult and puts a lot of limits on you
(basically the same limits the compiler has, though you're a lot smarter
than the compiler and will still do a better job, even playing by its
rules).

The other approach is to write everything in assembly. Without the
compiler's requirements, you have a lot more freedom. Some people would
say a lot more rope to hang yourself. But just to give you an idea, the
main difference (which matters most on the AVR) is that you get to
decide about register allocation on a global scale. You can, for
instance, decide to dedicate several registers to some interrupt routine
that needs a bunch of variables (quite common), rather than having to
slowly (and with lots of extra code) push the registers onto the stack,
load the variables from memory, and then to the reverse on exit from the
interrupt. All you have to do is simply not use those registers
anywhere else (or disable interrupts, but if you're coding such high
performance interrupt handlers, disabling interrupts for any length of
time is probably the last thing you'll want to do). There are a lot of
ways to achieve much faster, much smaller code than is ever possible
with the compiler, if it's never used anywhere and you don't have to
obey its rules.


So, if you really want to do an all assembly approach the "hard way" (as
Don will happily tell you I'm crazy to do), first try writing a very
simple bit of assembly code to just toggle a pin in an infinite loop.
It should be only a dozen bytes of output. Then build that parallel
port cable and try getting the MEGA168 chip to run it, using a 'scope or
multimeter (DC volts 2.5 if it's toggling high/low rapidly at 50%) or
even an LED to observe the pin. Then try sending some bytes out the
UART while watching via a terminal emulator. Once you get to that
stage, well, you'll be well on your way.

But in all likelihood, if your course is using the arduino, it may be
other approach of using C with little bits of assembly.


-Paul

Ben Bleything

unread,
Jan 28, 2008, 2:09:30 PM1/28/08
to A discussion list for dorkbot-pdx (portland, or)
On Mon, Jan 28, 2008, Paul Stoffregen wrote:
> #1: if the chip already has a bootloader programmed in, you can cause
> the bootloader to run and it will receive a download of code and write
> it into the chip (except for the portion which already has the
> bootloader, of course). This is how the arduino is normally used.

For what it's worth, I'm fairly sure you can write your asm, compile to
hex, and then upload it to an arduino using avrdude... you'll have to do
a little investigation to figure out how the arduino pins corespond to
the AVR ports, but that should be pretty easy to do.

Ben

Greg Borenstein

unread,
Jan 28, 2008, 2:13:51 PM1/28/08
to A discussion list for dorkbot-pdx (portland, or)
Ben,

How about tomorrow? Is that enough warning? :) Also, what time is best
to drop by your office?

Thanks!

-- Greg

Greg Borenstein

unread,
Jan 28, 2008, 2:16:49 PM1/28/08
to A discussion list for dorkbot-pdx (portland, or)
Paul,

Thanks for this intro, it was exactly what I've been looking for! Very
clear and well-explained to boot. Now, I think I'm finally starting to
understand all the steps involved in getting to a position where I
could be writing and running my first assembler code...

I may have to pick your brain more on this in the future.

yours,

Greg

Greg Borenstein

unread,
Jan 28, 2008, 2:26:19 PM1/28/08
to A discussion list for dorkbot-pdx (portland, or)
And I believe that is exactly my professor's plan for our work in the
course.

I think I'm starting to see the steps in front of me for getting
started down this path:

1) write some ASM and compile it to hex (any tips on the tools for
this?)
2) learn the Arduino pins-AVR port mapping
3) write an LED flasher hello world in ASM
4) upload hex of hello world to arduino with avrdude
5) profit :)

Is there something I'm missing here? Is there any danger of nuking my
Arduino's chip in the process here or does the bootloader offer some
protection/restrictions in this regard?

Ben -- I'd still like to take you up on the programmer/uC beer-lesson
offer if you're up for it. Never hurts to approach things like this
from multiple directions.

-- Greg

Ben Bleything

unread,
Jan 28, 2008, 2:35:52 PM1/28/08
to A discussion list for dorkbot-pdx (portland, or)
On Mon, Jan 28, 2008, Greg Borenstein wrote:
> 1) write some ASM and compile it to hex (any tips on the tools for
> this?)

The avr toolchain you can get from macports will have an assembler.
Check avrfreaks, I'm sure you'll find a small tutorial on getting
started there.

> 2) learn the Arduino pins-AVR port mapping

I'm pretty sure most of the pins are PORTC, but I don't know why so
don't trust me there.

> 3) write an LED flasher hello world in ASM

Cake.

> 4) upload hex of hello world to arduino with avrdude

Double cake. Steal the upload code from RAD ;)

> Is there something I'm missing here? Is there any danger of nuking my
> Arduino's chip in the process here or does the bootloader offer some
> protection/restrictions in this regard?

I think there's some danger of overwriting your bootloader if you muck
up the flags, but you can always reflash it. I've got an STK-500 (as do
a number of other folks) and would be happy to reflash it if it
comes to that.

That goes for everyone else, too... if you ever need something burned to
an AVR, let me know and I'll bring my programmer to next meeting.

> Ben -- I'd still like to take you up on the programmer/uC beer-lesson
> offer if you're up for it. Never hurts to approach things like this
> from multiple directions.

Emailed you off-list :)

Thomas Lockney

unread,
Jan 28, 2008, 2:47:12 PM1/28/08
to A discussion list for dorkbot-pdx (portland, or)
Ben Bleything wrote:
> On Mon, Jan 28, 2008, Greg Borenstein wrote:
>
>> Is there something I'm missing here? Is there any danger of nuking my
>> Arduino's chip in the process here or does the bootloader offer some
>> protection/restrictions in this regard?
>>
>
> I think there's some danger of overwriting your bootloader if you muck
> up the flags, but you can always reflash it. I've got an STK-500 (as do
> a number of other folks) and would be happy to reflash it if it
> comes to that.
>
If you have access to a system with a parallel port, you can always
build the very simple programmer from the arduino site, too. I believe
Paul linked to it in an earlier email in this thread. I haven't tried
building it yet, but I think I actually have all the parts lying around
here somewhere. If I ever seem to have free time again, I'll have to
give it a try.

~thomas

Paul Stoffregen

unread,
Jan 28, 2008, 3:10:42 PM1/28/08
to A discussion list for dorkbot-pdx (portland, or)

> Is there any danger of nuking my Arduino's chip in the process here or
> does the bootloader offer some protection/restrictions in this regard?

If the "fuse bits" were set properly when the bootloader was written,
then it is fully protected by hardware and can not be modified by itself
or any other code running on the chip. See section 24.4 on page 267 of
the datasheet for details.

Donald Delmar Davis

unread,
Jan 28, 2008, 5:04:47 PM1/28/08
to A discussion list for dorkbot-pdx (portland, or)
Greg,

I am sorry I didnt get this to you last night. 

But as thomas pointed out you are going to get most of what you need in the class so I feel like this may be time wasted.  

If you are running the Arduino then you have everything you need. 


Whatever platform you are using you need to find out where the arduino folk put the toolchain.
on my system it is in /Applications/arduino-0010/hardware/tools/avr/bin. The assembler is avr-as
the c compiler is avr-gcc,  and the programmer is uisp. 

(As all of the sample code from atmel is in its native assembler I have been maintaining a compatible assembler called avra.
The syntax used by avr-as uses a different example so I am scrambling to come up with a simple example. 
... I will create one by having avr-gcc skip the assembler 
$avr-gcc -c -mmcu=atmega168 -I. -gstabs -DF_CPU=16000000UL   -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=hdsp-230x.lst  -std=gnu99 -MD -MP -MF .dep/hdsp-230x.o.d hdsp-230x.c -S)
)

------------------------ snippet.
$ avr-as --mmcu=atmega168 hdsp-230x.s -o hdsp-230x.o
# (the above could also have been done as a call to avr-gcc)
$ avr-gcc  hdsp-230x.o -v -g -Wall -O2 -mmcu=atmega168 -Wl,-Map,hdsp230x.map -o hdsp230x.elf 
#(                                        ^ this will show you the underlying avr-ld command)
$ avr-objcopy -O ihex -R .eeprom hdsp-230x.elf hdsp-230x.hex 
$ uisp -v -dpart=atmega168 -dprog=avrisp -dserial=/dev/tty.usbserial-A1000gje --upload if=hdsp-230x.hex
------------------------ end 

On the mac the arduino serial device shows up as tty.usbserial-XXXXXX where XXXXXX is specific to the device.
(look at the selected device using your arduino settings for what should go after -dserial=/dev/...) 

Its not really trivial however most people just get a working makefile set up (google mfile) 

I have attached the one that is included in the osx-avr xcode templates.
Makefile

Donald Delmar Davis

unread,
Jan 28, 2008, 5:12:37 PM1/28/08
to A discussion list for dorkbot-pdx (portland, or)
Its a 3 dollar chip and its socketed.

:)

On the other hand don't mess with the fuses and load your programs
using the bootloader and you cant really go wrong.

I also heavily recomend using the ADABOOT loader and the dtr reset
hack (google 'em) if you aren't running a decimillia.

You can push your code its slick and DAMNED FAST.
(you will start to see how fat the java is in the ide as well).

Donald Delmar Davis

unread,
Jan 28, 2008, 8:21:23 PM1/28/08
to A discussion list for dorkbot-pdx (portland, or)
On the mac I highly recommend AvrMacPack. It is good enough to where I am no longer supporting OSX-AVR. Its complete its a universal binary and it rolls things out where they are easy to work with.

http://www.obdev.at/products/avrmacpack/download-de.html

Again if you have arduino you have a complete (albiet abit old) toolchain.

Good luck.

Don


Be a better friend, newshound, and know-it-all with Yahoo! Mobile. Try it now.

Greg Borenstein

unread,
Jan 28, 2008, 10:46:09 PM1/28/08
to A discussion list for dorkbot-pdx (portland, or)
Thanks for all this stuff, Don! It seems like just the thing.

I'll let you know how my first experiments go. Maybe I'll something to
show at the next Dorkbot...

-- Greg

> Be a better friend, newshound, and know-it-all with Yahoo! Mobile.

> Try it now._______________________________________________

Reply all
Reply to author
Forward
0 new messages