;;---------------------------------------------------------------------- ;; ECAD+Arch Workshop 4 ;; Your name ;; Your college ;; date ;;---------------------------------------------------------------------- AREA text,CODE ENTRY
;; This section is called "text", and contains code ;;; Print "Hello world" ;; Get the offset to the string in r4. ;; The variable '.' contains the value of ;; pc (r15) at the time of assembly. add r4,pc,#(hello -8 -.) loop ; This is a label ;; Call putchar to display each character ;; to illustrate how a loop works ldrb r0,[r4],#1 ; Get next byte, and post index r4 cmp r0,#0 ; Stop when we hit a null beq outputstring bl putchar b loop outputstring ;; Alternatively, use putsting to write out the ;; whole string in one go add r0,pc,#(hello -8 -.) bl putstring finish ;; Standard exit code: SWI 0x18 ;; with argument 0x20026 mov r0,#0x18 mov r1,#0x20000 add r1,r1,#0x26 SWI 0x123456 hello DCB "Hello World\n",0
END
;; I/O routines AREA text,CODE EXPORT printhex, putchar, putstring printhex ; Print number in r0 as 8 hex digits ; Conforms to APCS stmfd sp!,{r4,lr} add r2,pc,#(hex_digits-8-.) add r3,pc,#(print_hex_string-8-.) mov r4,#28 printhex_loop ;; For r4 = 28 to 0 step -4 mov r1,r0,lsr r4 ; Get digit n and r1,r1,#0x0f ; mask off lower nibble ldrb r1,[r2,r1] ; r1 now contains a hex number, look it up in table strb r1,[r3],#1 subs r4,r4,#4 bpl printhex_loop add r0,pc,#(print_hex_string-8-.) bl putstring ldmfd sp!,{r4,pc} hex_digits DCB "0123456789ABCDEF" print_hex_string DCB "12345678",0 ; storage for 8 digit hex string, null terminated ALIGN putchar ; Entry: Takes char in r0. ; Conforms to APCS ; Call SYS_WRITEC, with r1 containing a POINTER TO a character. ; SYS_WRITEC = 3, SYS_WRITE0 = 4, SYS_READC = 7 stmfd sp!,{r4-r12,lr} add r1,r15,#(putchar_temp -8 -.) strb r0,[r1] mov r0,#3 swi 0x123456 ldmfd sp!,{r4-r12,pc} putchar_temp DCB 0 ALIGN putstring ; Entry: Takes pointer to a null terminated string in r0 ; Conforms to APCS ; uses Call SYS_WRITE0 stmfd r13!,{r4-r12,lr} mov r1,r0 mov r0,#4 swi 0x123456 ldmfd r13!,{r4-r12,pc} END
IMPORT printhex IMPORT putchar IMPORT putstring
Start AXD with Project | Debug.
When AXD loads, it may ask you to choose a target. This refers to running the program on the ARM board, rather than in the emulator. As the link to the board is rather slow, we'll run the first half of this exercise in the emulator (select ARMUL).
Now, let's go back and look at the program's execution in more detail.
In summary, "step in" (F8) will do one instruction at a time; "step over" will do one instruction or subroutine at a time; and breakpoints halt the run whenever they are hit. They provide different granularities of control over debugging.
Now try it on the ARM board. To do this:
Write a program to produce a table of primes in hexadecimal. The table should be neatly printed on the console and should include an index number by each prime.
One method for determining if N is prime is to try dividing it by primes less that the sqrt(N). Alternatively you could use the Sieve of Erastothenes method. Note that the ARM does not have instructions that perform division and remainder operations. However, you can use the code from the Computer Design notes:
DivStart ; enter with numbers in r0 and r1 mov r2,#1 ; bit to control the division Div1 cmp r1,#0x80000000 ; shift r1 left until top bit set... cmpcc r1,r0 ; ...or r1>r0 movcc r1,r1,ASL#1 ; shift r1 left if require movcc r2,r2,ASL#1 ; shift r2 left if r1 is shifted bcc Div1 ; repeat whilst more shifting required mov r3,#0 ; zero r3 Div2 cmp r0,r1 ; test for possible subtraction subcs r0,r0,r1 ; subtract if r0>r1 addcs r3,r3,r2 ; put relevant bit into result movs r2,r2,LSR#1 ; shift control bit movne r1,r1,LSR#1 ; halve unless finished bne Div2 ; loop if there is more to do ; divide result in r3 ; remainder in r0 mov r1,r3 ; divide result (r0/r1) now in r1 mov r15,r14 ; return from subroutine
To define a memory area to store your table of primes, add the following code to the end of your code (just before the END):
ALIGN ; ensure allocated memory is word aligned primes_table % 4096 ; 4096 bytes is enough space for 1024 primes
You can obtain the start address for this table using:
add r5,r15,#(primes_table -8 -.)
This computes the address by determining how far the memory area is from the PC and then adding it to the PC. "." is short had for the current address for this instruction and the "-8" is required because the real PC is always 2 instructions ahead of the one being executed due to the pipelining.
Once you have written your primes program, comment it and put the answer to the following question in comments at the end of the code.