Code Examples from Class: Difference between revisions

From Class Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
Line 183: Line 183:
ALIGN
ALIGN
END
END
</nowiki>
* BCD Add
<nowiki>
; Subroutine to add two BCD numbers in 32 bit form with each nibble
; representing a digit.
; locals: r8 for digit counter, mask 0xf, r5 & r6 for masked addends,
; working BCD_carry, r7 for
; working result in r4
; inputs: r0+r1
; outupts: r0 result and r1 carry
; only r5-r8 are saved.
; Rob Frohne 11/12/13
stack_start EQU 0x40001000
AREA String_Compare, CODE
ENTRY
Start
ldr sp, =stack_start ; Tell where we will place the stack.
; (It goes down (lower addresses from here.)
ldr r0, =0x12345678 ; The two numbers to add.
ldr r1, =0x87654322
bl bcd_add
stop b stop

bcd_add ; The subroutine
stmfd sp!, {r5-r8,lr}
mov r8, #8 ; Set the counter to move through the eight digits
mov r7, #0 ; Set the carry to zero to start with
mov r3, #0 ; This is where the resulting digits of the sum are stored.
loop
and r5, r0, #0xf ; mask for the rightmost digit.
and r6, r1, #0xf
add r4, r5, r7 ; add carry
add r4, r4, r6 ; r4=r5+r6
subs r4, r4, #10 ; Subtract 10 (base 10) to see if there is a carry.
bmi no_carry
mov r7, #1 ; set the carry
b roll_to_next_digit
no_carry
mov r7, #0 ; set carry to zero
add r4, r4, #10 ; Add the 10 back in as there was no carry needed.
roll_to_next_digit
orr r3, r3, r4 ; Add thise digits into the sum.
ror r0, #4
ror r1, #4
ror r3, #4
subs r8, r8, #1 ; Decrement digit counter
bne loop ; If it isn't zero do the next digit.
mov r0, r3 ; Set the output registers. r0 is result. r1 is carry.
mov r1, r7
ldmfd sp!, {r5-r8,pc}
END
</nowiki>
</nowiki>

Revision as of 08:50, 13 November 2013

  • Factorial
; Factorial Calculation
; The answer is in R10

; Rob Frohne 2013

	GLOBAL Reset_Handler 
	AREA Factorial, CODE, READONLY
	ENTRY

Reset_Handler
		movs r8, #0 ; Take the factorial of this number, n.
		mov r10, #1	 ; 0! and 1! are 1
		beq stop   ; If r8 is zero we are done
		cmp r8, #1	 ; If r8 is 1, 
		beq stop	  ; we are done
		subs r9, r8, #1	; n-1
loop	mulne r10, r9, r8 ; n(n-1)
		mov r8, r10
		subs r9, r9, #1
		bne loop
stop 	b stop
		END


  • 64 Bit Add
VAL1A EQU 0xffffffff
VAL1B EQU 0x0000000f
VAL2A EQU 0x00000001
VAL2B EQU 0x00000001
	AREA LongAdd, CODE
	ENTRY
		ldr R0, = VAL1A
		ldr R1, = VAL1B
		ldr R2, = VAL2A
		ldr R3, = VAL2B
		adds R8,R0,R1
		adcs R9,R1,R3
stop 	b stop
	END

  • Copy to RAM
   AREA Exaddress, CODE, READONLY
   EXPORT Reset_Handler
Reset_Handler
   LDR R9, =list
   mov R7, #4 ; number in list
   ldr r6, =datastart 
loop
   ldr r8,[r9],#4
   str r8,[r6],#4
   subs r7,r7,#1
   bne loop
 
stop b stop
   ALIGN
list DCW 0x1111, 0x2222, 0x3333, 0x4444, 0x5555
   ALIGN
string DCB "This is a test.",0 ; This string is not used in the copy to ram program
string2 DCB 'T','h','i' ; This string2 is not used in the copy to ram program
   ALIGN
   AREA Thedata, DATA, NOINIT, READWRITE
datastart SPACE 20
 
   END

  • Subroutine Example1
; First Subroutine Example
; This program demonstrates using a subroutine,
; saving registers on the stack, etc.

; Rob Frohne, 1/3/2013

stack_start EQU 0x40001000
   AREA Subroutine_Example, CODE

   ENTRY

Start
   ldr sp, =stack_start ; Tell where we will place the stack.
                        ; (It goes down (lower addresses from here.)
   mov r1, #1 ; Store some numebers in some registers
   mov r2, #2
   mov r3, #3
   bl subroutine
stop b stop

; This subroutine saves the registers,
; messes up the registers locally,
; then restores the registers and returns.
subroutine
   stmfd sp!, {r1-r2,lr} ; save used registers and the link register (r14)
   mov r1,#0xffffffff ; mess up the registers
   mov r2, r1
   ldmfd sp!, {r1,r2,pc} ; pop the stack and return 
   END

  • Minimum of a Signed Number
; This program finds the minimum of a list of constant words in signed format
; The result is in r3 at the end of the routine.
; Rob Frohne 10/30/2013

	AREA Program, CODE, READONLY

	ENTRY

	ldr r0,=end		; load the beginning address of the code & initialize it as the pointer.
	ldr r2,=begin	; load the ending address of the code.
	mov r3,#0x7fffffff ; Initialize r3 as the most positive number.

loop	
	ldr r6,[r2],#4 ; load the next data into r6 and post increment r2 for the next data.
	cmp r6,r3 ; Find out if r6 > r3. result from r6-r3  like subs r7,r6,r3 without r6 necessary.
	bgt no_update	 ; If it is no update.
	mov r3,r6		; update if r6 is lower than r3.
no_update
	cmp r0,r2  ;  are we at the end yet
	bne loop		   ; if r7 != 0 then keep looping

stop b stop
ALIGN
begin
	DCD 0x8fffffff, 0x55555555, 0x44444444, 0x77777777, 0xffffffff
end	
	END 

  • Compare Two Null Terminated Strings
; Subroutine to compare two null terminated ASCII strings.
; The address where the two strings start are in r0 and r1
; The return is in r0, 1 for match and 0 for don't match.
; If they don't match, r1 gives the number of the first 
; character that didn't match, starting with 0.
; r2 and r3 are not protected.
; Rob Frohne 11/6/2013
stack_start EQU 0x40001000
	AREA String_Compare, CODE
    ENTRY
Start
	ldr sp, =stack_start ; Tell where we will place the stack.
                        ; (It goes down (lower addresses from here.)
	ldr r0, =string1
	ldr r1, =string2
	bl compare_strings
stop b stop

compare_strings
	stmfd sp!, {r2,r4,r5,lr} ; save used registers and the link register (r14)
	mov r2, #0 ; Initialize the counter for the first position.
loop
	ldrb r4,[r0],#1
	ldrb r5,[r1],#1
	cmp r5,r4
	bne do_not_match
	cmp r4, #0 ; check for end of string.
	beq match
	add r2, #1
	b loop
do_not_match
	mov r0, #0 ; don't match
	b finish
match
	mov r0, #1
finish
	mov r1,r2 ; Move the count into the result register.	
	ldmfd sp!, {r2,r4,r5,pc} ; pop the stack and return 
string1 
	DCB "This is the first string.",00	; For testing purposes.
	ALIGN
string2 
	DCB "This is the first string.",00
	ALIGN
        END

  • BCD Add
; Subroutine to add two BCD numbers in 32 bit form with each nibble
; representing a digit.
; locals: r8 for digit counter, mask 0xf, r5 & r6 for masked addends,
; working BCD_carry, r7 for
; working result in r4
; inputs: r0+r1
; outupts: r0 result and r1 carry
; only r5-r8 are saved.
; Rob Frohne 11/12/13
stack_start EQU 0x40001000
	AREA String_Compare, CODE
    ENTRY
Start
	ldr sp, =stack_start ; Tell where we will place the stack.
                        ; (It goes down (lower addresses from here.)
	ldr r0, =0x12345678	  ; The two numbers to add.
	ldr r1, =0x87654322
	bl bcd_add
stop b stop

bcd_add	; The subroutine
	stmfd sp!, {r5-r8,lr}
	mov r8, #8 ; Set the counter to move through the eight digits
	mov r7, #0 ; Set the carry to zero to start with
	mov r3, #0	; This is where the resulting digits of the sum are stored.
loop
	and r5, r0, #0xf  ; mask for the rightmost digit.
	and r6, r1, #0xf
	add r4, r5, r7 ; add carry
	add r4, r4, r6 ; r4=r5+r6
	subs r4, r4, #10 ; Subtract 10 (base 10) to see if there is a carry.
	bmi no_carry
	mov r7, #1 ; set the carry
	b roll_to_next_digit
no_carry
	mov r7, #0 ; set carry to zero
	add r4, r4, #10 ; Add the 10 back in as there was no carry needed.
roll_to_next_digit
	orr r3, r3, r4 ; Add thise digits into the sum.
	ror r0, #4
	ror r1, #4
	ror r3, #4
	subs r8, r8, #1	 ; Decrement digit counter
	bne loop	  ; If it isn't zero do the next digit.
	mov r0, r3 ; Set the output registers. r0 is result. r1 is carry.
	mov r1, r7
	ldmfd sp!, {r5-r8,pc}
	END