CMPS-2240 Lab-6
ARM-32 programming

Gordon Griesel
Department of Computer and Electrical Engineering and Computer Science
California State University, Bakersfield

Introduction

Goals:
• Write an ARM Hello World program.
• Make your program print Hello World multiple times using a loop.
• Write an ARM program that plays 3-5-Bingo!

Resources:
ARM Assembly by Example
ARM instruction set
ARM Registers
EABI Syscall table
Stack frame
Sample programs
Divide in ARM-32

Get the files:

   log on to Odin
   $ cd
   $ cd 2240/6
   $ cp /home/fac/gordon/public_html/2240/code/lab6/* .

How to run an ARM-32 program on Odin
------------------------------------

1. Write an ARM hello-world program named myhello.s
   vi myhello.s

2. Assemble your program, creating an object file.
   arm-linux-gnueabi-as myhello.s -o hello.o

3. Link and produce an executable file.
   arm-linux-gnueabi-ld hello.o -o hello

4. Run your executable
   ./hello


How to use the make utility to build your ARM programs
------------------------------------------------------

For myhello.s program...

vi Makefile

Enter the text below.

all: hello

hello: hello.o
	arm-linux-gnueabi-ld hello.o -o hello

hello.o: hello.s
	arm-linux-gnueabi-as myhello.s -o hello.o 

clean:
	rm -f hello
	rm -f *.o

Note:
The indented line must use hard-tabs for indenting.

 Part 1

Copy hello.s to myhello.s
Modify myhello.s to display several times using a loop.
Use the assembler to create an object file.
Use the linker to create your executable file.
Run your program.


odin:~/2240/6$ arm-linux-gnueabi-as myhello.s -o hello.o
odin:~/2240/6$ arm-linux-gnueabi-ld hello.o -o hello
odin:~/2240/6$ ./hello
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!


Part 2

Play the 3-5-Bingo game.

Name your program: bingo.s

Write an ARM-32 program that displays the numbers 1 to 100.
but not all the numbers.

If a number is divisible by 3, display it.
If a number is divisible by 5, display it.
If a number is divisible by 3 and by 5, display Bingo!

Do you remember how to divide by 3 without a divide command?

Use Fixed-point math for this, using one of the ARM registers.
We will review this again in class.

======================================================================
How to divide by 3 and look at the remainder...
   1. Multiply your number by 0x55555556
   2. Look at the result in the low register only.
   3. If the value is less than about 200, count it as zero.

How to divide by 5 and look at the remainder...
   1. Multiply your number by 0x33333334
   2. Look at the result in the low register only.
   3. If the value is less than about 200, count it as zero.

Here is the result of the divides above on numbers 1 to 40.
Notice there is some residue in the remainder, when it should be zero.
Check for near zero in your tests. Not exactly zero.

num  rem   remainder bit pattern
---  ---   --------------------------------
  3    2   00000000000000000000000000000010
  5    4   00000000000000000000000000000100
  6    4   00000000000000000000000000000100
  9    6   00000000000000000000000000000110
 10    8   00000000000000000000000000001000
 12    8   00000000000000000000000000001000
 15   10   00000000000000000000000000001010
 15   12   00000000000000000000000000001100
 18   12   00000000000000000000000000001100
 20   16   00000000000000000000000000010000
 21   14   00000000000000000000000000001110
 24   16   00000000000000000000000000010000
 25   20   00000000000000000000000000010100
 27   18   00000000000000000000000000010010
 30   20   00000000000000000000000000010100
 30   24   00000000000000000000000000011000
 33   22   00000000000000000000000000010110
 35   28   00000000000000000000000000011100
 36   24   00000000000000000000000000011000
 39   26   00000000000000000000000000011010
 40   32   00000000000000000000000000100000

Can you see where Bingo! should be printed?
======================================================================

Alternate method using ARM-32 sdiv command:

As your numbers are listing, divide each with sdiv.

   sdiv quotient, dividend, divisor

How to check for a remainder:

multiply quotient times divisor

if result is equal to dividend
    remainder is zero
else
    remainder is not zero

======================================================================

There is a 3rd method also, which is to use counters:

Do not use multiply or divide.
Setup 3 counters using general purpose registers of your choice.
Increment the counters each loop pass.
Check your counters being equal to 3, 5, or 15.
Reset the counters as needed.

======================================================================

Some extra credit for getting the program working multiple ways.

  1. Fixed-point multiply method   bingo.s
  2. sdiv with multiply method     bingo2.s
  3. No divide or multiply         bingo3.s

======================================================================
How to get started
------------------
1. You can start with your myhello.s program loop.
   cp myhello.s bingo.s

2. Make your program display the numbers 1 through 20 or so.
   When you get that working...

3. Choose one of the methods described above.

Output sample...


$ ./bingo
3
5
6
9
10
12
Bingo!
18
20
21
...
...
...

Fixed point format:

32-bit register:  0000000000000000.0000000000000000      
                  integer          fraction


After a fixed-point divide:

32-bit register:  0000000000000000.0000000000000000      
                  quotient         remainder


How would you look at just the fraction part of the register?

Ask Gordon or Pablo for help.

The following programs will be collected

2240/6/myhello.s 2240/6/bingo.s 2240/6/Makefile 2240/6/bingo2.s 2240/6/bingo3.s I will assemble and run your bingo programs like this... arm-linux-gnueabi-as bingo.s -o bingo.o arm-linux-gnueabi-as atoi.s -o atoi.o arm-linux-gnueabi-as itoa.s -o itoa.o arm-linux-gnueabi-as printf.s -o printf.o arm-linux-gnueabi-ld bingo.o atoi.o itoa.o printf.o -o bingo ./bingo The first line will contain: bingo.s, bingo2.s, or bingo3.s