Learning ARM assembly


17 posts
by titeuf_87 » Tue Nov 13, 2012 6:44 pm
Hello all,

I'm not sure where to post this since it's not actually bare metal in the sense that you don't need an OS to run, but on the other hand this is where most asm topics are.

I'm learning ARM assembly, never having done any assembly before and I made the "99 bottles of beer" program.

Here is my result:
Code: Select all
.globl _start

_start:
        mov r4, $99
loop:
        ldr r0, =string1
        ldr r1, =bottles
        ldr r3, =plural
        mov r2, r4
        cmp r2, $1
        addeq r3, $1
        bl sprintf

        sub r4, $1

        ldr r0, =string2
        ldr r1, =bottles
        ldr r3, =plural
        mov r2, r4
        cmp r2, $1
        addeq r3, $1
        bl sprintf

        ldr r0, =lyric
        ldr r1, =string1
        ldr r2, =string2
        bl printf

        cmp r4, $0
        bne loop

        mov r0, $0
        bl exit

lyric:
        .asciz "%1$s on the wall, %1$s.\nTake one down, pass it around, %2$s on the wall.\n\n"

bottles:
        .asciz "%d bottle%s of beer"

plural:
        .asciz "s"

.data
string1:
        .space 19
string2:
        .space 19


This needs Linux to run (tested on Raspbian). It would probably work on other OSes too since there is nothing specific to Linux here, just needs a c library.

To compile, do the following:
Code: Select all
as -o beer.o beer.s
ld -dynamic-linker /lib/ld-linux.so.3 -o beer beer.o -lc

Since I'm learning, any comments on how to improve this are welcome :)
Posts: 5
Joined: Tue Nov 13, 2012 6:39 pm
by PeterU » Fri Jan 18, 2013 6:43 pm
Thanks for posting this!

I thought I'd have a play with ARM assembly on my Pi and it was nice that you'd shared a simple program that I could type in and verify that it worked, and then modify!

Have you done anything else with this since?
User avatar
Posts: 1
Joined: Fri Jan 18, 2013 6:38 pm
by titeuf_87 » Sat Jan 19, 2013 3:00 pm
Glad that this helped you out!

I haven't really done anything else assembly wise though since then, went on to play a bit with c, then wandered into the OpenGl ES world, which seems to be a lot harder than this...

Good luck!
Posts: 5
Joined: Tue Nov 13, 2012 6:39 pm
by dwelch67 » Sat Jan 19, 2013 3:33 pm
titeuf_87 wrote:Since I'm learning, any comments on how to improve this are welcome :)


Your code looks fine, you should disassemble to see how the =something thing is actually implemented.

David
Posts: 412
Joined: Sat May 26, 2012 5:32 pm
by DexOS » Sat Jan 19, 2013 6:42 pm
Nice work titeuf_87.
Batteries not included, Some assembly required.
User avatar
Posts: 860
Joined: Wed May 16, 2012 6:32 pm
by titeuf_87 » Sat Jan 19, 2013 10:27 pm
dwelch67 wrote:
titeuf_87 wrote:Since I'm learning, any comments on how to improve this are welcome :)


Your code looks fine, you should disassemble to see how the =something thing is actually implemented.

David

I did do that, although had to recheck now since it's been a while. It gets loaded from an offset of the pc register.

DexOS wrote:Nice work titeuf_87.

Thanks!
Posts: 5
Joined: Tue Nov 13, 2012 6:39 pm
by DexOS » Sat Jan 19, 2013 11:17 pm
Theres a nice 512 byte arm assembly pong game example here:
http://wiki.gp2x.org/wiki/Pong_Demo

It would need converting for the PI, as it for the gp2x, which was both arm and had linux on it, so should not be too hard.

NOTE: The source is in the "Sourcecode: [2]" link
Batteries not included, Some assembly required.
User avatar
Posts: 860
Joined: Wed May 16, 2012 6:32 pm
by dextrus » Sat Jan 19, 2013 11:47 pm
For a really good source of tutorials and help, don't forget the Game Boy Advanced, which uses an Arm 7 processor. There's shed loads of stuff out there for this directly relevant to the Pi. Just alter your searches a bit and look GBA-wards.

/Dextrus
Have more FUN with your Pi. Visit www.pi-fun.com
Posts: 119
Joined: Tue Jan 24, 2012 10:10 pm
Location: Eastleigh, Hampshire
by sej7278 » Tue Jan 22, 2013 7:02 pm
Last time I did any ARM assembly was on an SA-RiscPC so that was ARMv4.

Oddly enough I've got shedloads of x86 Linux machines but haven't been motivated to do any programming on them in a while (other than packaging, e.g. compiling Android or making RPMs/DEBs) something about getting my Pi is exciting me - I'll probably get back into some electronics after 15 or so years and refresh my Python.

Anyway, I'd be interested in any Linux+ARMv6 assembler tutorials you can find (probably a few Android ones dotted about) in the meantime I've just got to fire up RISC OS5 and try out my old BASIC programs :mrgreen:
Posts: 232
Joined: Tue Jan 22, 2013 6:43 pm
by bobblestiltskins » Wed Jan 23, 2013 11:40 am
I wrote http://www.fourtheye.org/armasm.shtml about ARM assembly on my SheevaPlug - but all the code works on a RPi. I do not know if this helps?

I looked a bit more here http://www.fourtheye.org/armstrong.shtml
Posts: 16
Joined: Wed Aug 29, 2012 11:10 am
by titeuf_87 » Wed Jan 23, 2013 9:09 pm
What Dextrus mentioned: I used a GBA tutorial to learn arm assembly...although I can't seem to find which one anymore in particular.

Edit: just found the tutorial back, it's this one.
Posts: 5
Joined: Tue Nov 13, 2012 6:39 pm
by DexOS » Wed Jan 23, 2013 9:32 pm
bobblestiltskins wrote:I wrote http://www.fourtheye.org/armasm.shtml about ARM assembly on my SheevaPlug - but all the code works on a RPi. I do not know if this helps?

I looked a bit more here http://www.fourtheye.org/armstrong.shtml

Nice work bobblestiltskins.
Batteries not included, Some assembly required.
User avatar
Posts: 860
Joined: Wed May 16, 2012 6:32 pm
by rpdom » Thu Jan 24, 2013 9:25 am
Thank you for a nice example of how to use ARM code under linux. To someone who is trying to get back into ARM assembler after many years it has proved very useful. My previous code was mostly written using the BBC Basic assembler on ARM1, 2 & 3 systems.

I had been looking for a way to try and debug some of my bare metal code from the Baking Pi lessons, and this showed me how I could run some of the code on a running system and display what it is doing. (Instead of doing the actual GPIO set/reset etc, just display what is being set to what) I haven't fixed the problem yet, but I'll get there ;)

Just one question. When "exit" is called at the end, it is with "bl". As it never returns from the exit, is the "l" necessary? I can see that it won't actually affect anything, just wondering if it is needed or if a straight "b" would do the same job.
Posts: 3370
Joined: Sun May 06, 2012 5:17 am
Location: Essex, UK
by titeuf_87 » Thu Jan 24, 2013 5:27 pm
rpdom wrote:Just one question. When "exit" is called at the end, it is with "bl". As it never returns from the exit, is the "l" necessary? I can see that it won't actually affect anything, just wondering if it is needed or if a straight "b" would do the same job.


Good question. I wasn't sure myself so I tried with just b, and it works too.
Posts: 5
Joined: Tue Nov 13, 2012 6:39 pm
by dwelch67 » Thu Jan 24, 2013 10:32 pm
If you call exit() from a C program and compile it, the compiler should not make any assumptions about the function and with any other function should assume there is a return that will happen, so use the bl instruction. As humans, who have verified that the exit function does in fact terminate the program and not return, in assembly language we can certainly choose the unconditional branch or branch link. To be completely safe though, you might want to do this:

Code: Select all
bl exit
b .


If exit does happen to not do what you think, and returns then you safely go into an infinite loop rather than executing garbage. I would assume a compiler would do this:

Code: Select all
bl exit
; prep return value in r0
bx lr


As far as b vs bl, both take the same instruction space, one might have a longer reach than the other I would have to check, for the most part though it doesnt really matter as far as calling exit() in a linux program goes. If you are doing a thumb/arm mixture then you would need bx not b nor bl (or use a trampoline like gcc does).

dwelch67
Posts: 412
Joined: Sat May 26, 2012 5:32 pm
by rpdom » Fri Jan 25, 2013 10:05 am
dwelch67 wrote:If you call exit() from a C program and compile it, the compiler should not make any assumptions about the function and with any other function should assume there is a return that will happen, so use the bl instruction. As humans, who have verified that the exit function does in fact terminate the program and not return, in assembly language we can certainly choose the unconditional branch or branch link. To be completely safe though, you might want to do this:

Code: Select all
bl exit
b .


If exit does happen to not do what you think, and returns then you safely go into an infinite loop rather than executing garbage.


Thank you. That does make sense :)
Posts: 3370
Joined: Sun May 06, 2012 5:17 am
Location: Essex, UK
by dextrus » Thu Jan 31, 2013 12:30 am
That's a really good source! It's very approachable and well written for the newcomer. I might nick this for teaching duties!

/Dextrus

titeuf_87 wrote:What Dextrus mentioned: I used a GBA tutorial to learn arm assembly...although I can't seem to find which one anymore in particular.

Edit: just found the tutorial back, it's this one.
Have more FUN with your Pi. Visit www.pi-fun.com
Posts: 119
Joined: Tue Jan 24, 2012 10:10 pm
Location: Eastleigh, Hampshire