Difference between revisions of "Tutorial: Assembly Language with the Raspberry Pi"
(→Passing Parameters by Value) |
(→Setup) |
||
Line 14: | Line 14: | ||
<br /> | <br /> | ||
* Please refer to [[Tutorial: Client/Server on the Raspberry Pi| this page]] for information on how to set your system up. I'm using a Mac connected to the Pi via wifi, and '''ssh'''-ing to it in a Terminal window. | * Please refer to [[Tutorial: Client/Server on the Raspberry Pi| this page]] for information on how to set your system up. I'm using a Mac connected to the Pi via wifi, and '''ssh'''-ing to it in a Terminal window. | ||
+ | * The controller used in this tutorial is a Raspberry Pi 2, running 2015-05-05-raspbian-wheezy. No special customization was performed, except setting up USB-based Wifi communication. | ||
<br /> | <br /> | ||
Revision as of 20:00, 3 July 2015
--D. Thiebaut (talk) 08:19, 3 July 2015 (EDT)
This is a very basic introduction to assembly code on the ARM processor of the Raspberry Pi. It is intended to provide examples of code for typical operations one may want to do, not as an introduction to assembly language.
You can find more tutorials here.
Contents
Reference
Setup
- Please refer to this page for information on how to set your system up. I'm using a Mac connected to the Pi via wifi, and ssh-ing to it in a Terminal window.
- The controller used in this tutorial is a Raspberry Pi 2, running 2015-05-05-raspbian-wheezy. No special customization was performed, except setting up USB-based Wifi communication.
Program that Returns an Exit Code
- This example is taken from thinkingeek.com's tutorial on assembly on the Pi. It is repeated here for completeness. Refer to thinkingeek.com's excellent tutorials for a deeper understanding of what is going on.
/* first.s from thinkingeek.com http://thinkingeek.com/2013/01/09/arm-assembler-raspberry-pi-chapter-1/ Defines a main function that returns 2 as an exit code. */ .global main /* 'main' must be visible by the C compiler. */ .func main /* declare 'main' as a function */ main: mov r0, #2 /* load immediate value 2 into Register r0 */ bx lr /* return 2 to Operating Sytem */
Create the program
Note that all the commands below must be run on the Raspberry Pi, either directly, if you have connected a keyboard and video monitor to it, or remotely, via ssh and an ethernet cable or a Wifi link.
- ssh to the Pi using the Terminal Window. Refer to this page for how to do this.
- Use your favorite editor on the Pi (mine is emacs), create a file called first.s and enter this code. If you are interested in bypassing the editor, simply type this:
cat > first.s
- and paste the code above. Then press ENTER, Control-D, ENTER, and this should create the file for you.
- To verify that the file is created, type this:
cat first.s
- and you should see the contents of the file.
Assemble, Compile, and Run!
- Assemble the code to create an object file:
as -o first.o first.s
- This will create the object file first.o
- Compile it. The object file is not executable. A C compiler can read it, though, and transform it into an executable.
gcc -o first first.o
- This takes the object file first.o and generates the executable file first.
- Run it!
./first
- The program should run and not display anything. As long as you don't get an error, your have been successful. The reason there is no output is that the program does not explicitly print anything, and simply returns a number that the operating system gets. Whenever you run a program on the command line, it returns a number at the end, revealing some status information about whether the program was successful in doing whatever we asked it to do. To reveal the number, we can use the shell command "echo $?" which displays the number returned by the last program that was run from the command line.
./first | echo $? 2
- The number 2 should be printed.
Hello World!
- Here's the program:
@ hello.s @ D. Thiebaut @ Just your regular Hello World program! @ @ --------------------------------------- @ Data Section @ --------------------------------------- .data string: .asciz "\nHello World!\n" @ --------------------------------------- @ Code Section @ --------------------------------------- .text .global main .extern printf main: push {ip, lr} ldr r0, =string bl printf pop {ip, pc}
Assemble, Link/Compile, and Run
Arithmetic With Integer Variables
@ sum1.s @ D. Thiebaut @ add 2 variables together @ @ --------------------------------------- @ Data Section @ --------------------------------------- .data .balign 4 string: .asciz "\na + b = %d\n" a: .word 33 b: .word 44 c: .word 0 @ will contain a+b @ --------------------------------------- @ Code Section @ --------------------------------------- .text .global main .extern printf main: ldr r1, =a @ get address of a into r1 ldr r1, [r1] @ get a into r1 ldr r2, =b @ get address of b into r2 ldr r2, [r2] @ get b into r2 add r1, r1, r2 @ add r1 to r2 and store into r1 ldr r2, =c @ get address of c into r2 str r1, [r2] @ store r1 into c push {ip, lr} @ push return address + dummy register @ for alignment ldr r0, =string @ get address of string into r0 ldr r1, [r2] @ pass c=a+b into r1 bl printf @ print string and r1 as param pop {ip, pc} @ pop return address into pc
Arithmetic With Integer Variables (Version 2)
- This version performs the same arithmetic, but generates a more sophisticated output.
@ sum2.s @ D. Thiebaut @ add 2 variables together and print the result. @ @ --------------------------------------- @ Data Section @ --------------------------------------- .data .balign 4 string: .asciz "\n%d + %d = %d\n" a: .word 33 b: .word 44 c: .word 0 @ will contain a+b @ --------------------------------------- @ Code Section @ --------------------------------------- .text .global main .extern printf main: ldr r1, =a @ get address of a into r1 ldr r1, [r1] @ get a into r1 ldr r2, =b @ get address of b into r2 ldr r2, [r2] @ get b into r2 add r1, r1, r2 @ add r1 to r2 and store into r1 ldr r2, =c @ get address of c into r2 str r1, [r2] @ store r1 into c push {ip, lr} @ push return address + dummy register @ for alignment ldr r0, =string @ get address of string into r0 ldr r1, =a @ r1 <- a ldr r1, [r1] ldr r2, =b @ r2 <- b ldr r2, [r2] ldr r3, =c @ r3 <- c ldr r3, [r3] @ bl printf @ print string and pass params @ into r1, r2, and r3 pop {ip, pc} @ pop return address into pc
Passing Parameters by Value
- In this example, two ints are passed by value to the function sumFunc. The function adds them up, and returns the result in r0.
@ sum3.s @ D. Thiebaut @ Illustrates how to pass 2 ints by value @ to a function that adds them up and returns @ the sum in r0. @ --------------------------------------- @ Data Section @ --------------------------------------- .data .balign 4 string: .asciz "\n%d + %d = %d\n" a: .word 33 b: .word 44 c: .word 0 @ will contain a+b @ --------------------------------------- @ Code Section @ --------------------------------------- .text .global main .extern printf @ --------------------------------------- @ sumFunc: gets 2 ints in r1 and r2, adds @ them up and saves the results in @ r0. sumFunc: push {ip, lr} add r0, r1, r2 pop {ip, pc} @ --------------------------------------- @ main: passes 2 ints to sumFunc and prints @ the resulting value using printf main: push {ip, lr} @ push return address + dummy register @ for alignment ldr r1, =a @ get address of a into r1 ldr r1, [r1] @ get a into r1 ldr r2, =b @ get address of b into r2 ldr r2, [r2] @ get b into r2 bl sumFunc @ pass (r1, r2) to sumFunc @ gets sum back in r0 ldr r2, =c @ get address of c into r2 str r0, [r2] @ store r0 into c @ printf( "%d + %d = %d\n", r1, r2, r3 ) @ (format-string address passed in r0) ldr r0, =string @ get address of string into r0 ldr r1, =a @ r1 <- a ldr r1, [r1] ldr r2, =b @ r2 <- b ldr r2, [r2] ldr r3, =c @ r3 <- c ldr r3, [r3] @ bl printf @ print string and pass params @ into r1, r2, and r3 @ return to OS pop {ip, pc} @ pop return address into pc
pi@raspberrypi ~/temp $ as -o sum3.o sum3.s pi@raspberrypi ~/temp $ gcc -o sum3 sum3.o pi@raspberrypi ~/temp $ ./sum3 33 + 44 = 77 pi@raspberrypi ~/temp $
Passing Parameters by Reference
@ sum4.s @ D. Thiebaut @ Illustrates how to pass 2 ints by reference @ to a function that adds them up and returns @ the sum in r0. @ --------------------------------------- @ Data Section @ --------------------------------------- .data .balign 4 string: .asciz "\n%d + %d = %d\n" a: .word 33 b: .word 44 c: .word 0 @ will contain a+b d: .word 55 e: .word 22 @ --------------------------------------- @ Code Section @ --------------------------------------- .text .global main .extern printf @ --------------------------------------- @ sumFunc: gets 2 ints in r1 and r2, adds @ them up and saves the results in @ r0. sumFunc: push {ip, lr} ldr r1, [r1] ldr r2, [r2] add r0, r1, r2 pop {ip, pc} @ --------------------------------------- @ printFunc: prints [r1], [r2], r3 in this way. @ printf( "%d + %d = %d\n", r1, r2, r3 ) @ (format-string address passed in r0) printFunc: push {ip, lr} ldr r0, =string @ get address of string into r0 ldr r1, [r1] ldr r2, [r2] mov r3, r3 @ not necessary... bl printf @ print string and pass params @ into r1, r2, and r3 pop {ip, pc} @ --------------------------------------- @ main: passes 2 ints to sumFunc and prints @ the resulting value using printf main: push {ip, lr} @ push return address + dummy register @ for alignment @ c = a + b ldr r1, =a @ get address of a into r1 ldr r2, =b @ get address of b into r2 bl sumFunc @ pass (r1, r2) to sumFunc @ gets sum back in r0 ldr r3, =c @ get address of c into r2 str r0, [r3] @ store r0 into c @ print a + b = c ldr r1, =a ldr r2, =b ldr r3, =c ldr r3, [r3] bl printFunc @ return to OS pop {ip, pc} @ pop return address into pc
pi@raspberrypi ~/temp $ as -o sum4.o sum4.s pi@raspberrypi ~/temp $ gcc -o sum4 sum4.o pi@raspberrypi ~/temp $ ./sum4 33 + 44 = 77 pi@raspberrypi ~/temp $