📄 bbu_library.s
字号:
bl BBU_FMTDIG ; Yes - Format output byte
;
; Get 1,000,000s digit
;
43 mov r0, r1 ; Copy remainder to r0
ldr r1, =1000000 ; Load divisor
bl BBU_U32Div ; Perform unsigned 32 bit divide
cmp r4, #7 ; Display 7 digits or more?
blt %F44 ; No - don't output this digit
bl BBU_FMTDIG ; Yes - Format output byte
;
; Get 100,000s digit
;
44 mov r0, r1 ; Copy remainder to r0
ldr r1, =100000 ; Load divisor
bl BBU_U32Div ; Perform unsigned 32 bit divide
cmp r4, #6 ; Display 6 digits or more?
blt %F45 ; No - don't output this digit
bl BBU_FMTDIG ; Yes - Format output byte
;
; Get 10,000s digit
;
45 mov r0, r1 ; Copy remainder to r0
ldr r1, =10000 ; Load divisor
bl BBU_U32Div ; Perform unsigned 32 bit divide
cmp r4, #5 ; Display 5 digits or more?
blt %F46 ; No - don't output this digit
bl BBU_FMTDIG ; Yes - Format output byte
;
; Get 1,000s digit
;
46 mov r0, r1 ; Copy remainder to r0
ldr r1, =1000 ; Load divisor
bl BBU_U32Div ; Perform unsigned 32 bit divide
cmp r4, #4 ; Display 4 digits or more?
blt %F47 ; No - don't output this digit
bl BBU_FMTDIG ; Yes - Format output byte
;
; Get 100s digit
;
47 mov r0, r1 ; Copy remainder to r0
ldr r1, =100 ; Load divisor
bl BBU_U32Div ; Perform unsigned 32 bit divide
cmp r4, #3 ; Display 3 digits or more?
blt %F48 ; No - don't output this digit
bl BBU_FMTDIG ; Yes - Format output byte
;
; Get 10s digit
;
48 mov r0, r1 ; Copy remainder to r0
ldr r1, =10 ; Load divisor
bl BBU_U32Div ; Perform unsigned 32 bit divide
cmp r4, #2 ; Display 2 digits or more?
blt %F49 ; No - don't output this digit
bl BBU_FMTDIG ; Yes - Format output byte
;
; Write out last digit (in remainder)
;
49 add r1, r1, #0x30 ; Turn into ASCII
strb r1, [r3], #1 ; Store in output buffer
mov r1, r3 ; Update pointer in r1 for return to caller
ldmfd sp!, {r3, r4, r5, pc}; Restore r2-r5, & return to caller
ENDFUNC
;
;*********************************************************************************
;
; **************
; * *
; * BBU_FMTDIG * Formats and outputs a digit of a numberic string
; * *
; **************
;
; This is ONLY called from the BBU_ENCODE subroutine!
; Stack pointer is NOT used!!!!
; Uses saved registers in calling routine
;
; Last Update: 3-Aug-1004
;
BBU_FMTDIG FUNCTION
cmp r0, #0 ; Is r0 equal to zero?
bne %F51 ; No - skip the following
;
; Byte is equal to zero - see if this is a leading digit
;
cmp r5, #0 ; Is this a leading digit?
bne %F51 ; No - force printing of this byte
cmp r2, #0 ; Prefix with no byte?
beq %F52 ; Yes - just exit
mov r0, #0x30 ; Set byte to ASCII zero
cmp r2, #1 ; Prefix with ASCII zero byte?
streqb r0, [r3], #1 ; Yes store '0' in output buffer
mov r0, #0x20 ; Set byte to ASCII <space>
cmp r2, #2 ; Prefix with ASCII <space> byte?
streqb r0, [r3], #1 ; Yes store <space> in output buffer
b %F52 ; Exit path
51 add r0, r0, #0x30 ; Turn digit into ASCII byte
add r5, r5, #1 ; Increment work register
strb r0, [r3], #1 ; Output byte and increment pointer
52 mov pc, lr ; return to caller
ENDFUNC
;
;*********************************************************************************
;
; **********************
; * *
; * BBU_get_hex_nibble * Converts and ASCII byte (0-F) into a hex value
; * *
; **********************
;
; Last Update: 1-Apr-1005
;
; PARAMETER PASSING:
;
; INPUT - r0 contains pointer to the byte to be decoded
;
;
; OUTPUT - r0 points to next byte
; r1 contains decoded value (0x0-0xF) if sucessful
; (0x10) if non A-F byte
; (0x20) if NULL byte
;
BBU_get_hex_nibble FUNCTION
stmfd sp!, {r2, lr} ; Save r2 & link reg on stack
mov r1, #0x20 ; Set r1 as NULL byte indicator
ldrb r2, [r0], #1 ; Fetch byte & increment pointer
cmp r2, #0 ; End of string?
beq %F20 ; Yes - take exit path
mov r1, #0x10 ; set r1 as error indicator
cmp r2, #0x60 ; Lower case character?
subgt r2, r2, #0x20 ; Yes - Convert to upper case
cmp r2, #'0' ; Compare byte to ASCII zero
blt %F20 ; Less and zero - error, return
cmp r2, #'F' ; Compare to ASCII "F"
bgt %F20 ; Greater than ASCII "F" - error, return
;
; Byte is between ASCII 0 and ASCII F - there are still a few character in
; between that can cause an error
;
sub r2, r2, #'0' ; Scale ASCII zero to binary zero
cmp r2, #10 ; Is the value in the 0-9 range?
movlt r1, r2 ; Yes - copy to r1
blt %F20 ; ...and return
subs r2, r2, #7 ; Scale ASCII "A" to binary b1010
cmp r2, #0xA ; Compare to hex value of "A"
blt %F20 ; r2 has invalid value - Error, return
mov r1, r2 ; Otherwise, copy r2 to r1 and return
20 ldmfd sp!, {r2, pc} ; Restore r2 & pc (return to caller)
ENDFUNC
;
;*********************************************************************************
;
; ****************
; * *
; * BBU_mem_size * Subroutine
; * *
; ****************
;
; This subroutine attempts to size the memory starting at the address given in r0 and
; returns the number of size units in r1
;
; PARAMETER PASSING:
;
; INPUTS:
; r0 = starting address where the memory size tests are to begin
; r1 = memory increment size (Typically, 0x100000 for 1Mb, or 0x400 for 1Kb)
; OUTPUTS:
; r1 = Number of increments detected.
; r2 = Memory size (in bytes) - also saved at address in r0
;
; NOTES:
;
; The program writes a value to memory at (increment size) increments and checks to make sure
; that the base address has not been modified (due to memory wrap) to calculate the
; size of the memory.
;
BBU_mem_size FUNCTION
stmfd sp!, {r3-r4, lr} ; Save used registers & link on stack
mov r2, r1 ; Copy increment size to r2
mov r9, #0 ; Clear r9 to prevent text message on data abort
mov r1, #0 ; Zero the number of size units detected
mov r4, r0 ; Copy base address to r4
;
; Start writing to memory in size unit increments and check the base address to make sure the
; data has not been written over due to a "memory wrap".
;
str r0, [r0] ; Load base address
10 add r4, r4, r2 ; Bump address by 1 size unit
str r4, [r4] ; Store data here
ldr r3, [r0] ; check base address for data wrap
cmp r3, r0 ; Is the base address data still OK?
bne %F20 ; No - data must have wraped - take exit
ldr r3, [r4] ; Yes - Read back the data just written
cmp r3, r4 ; is the data still there?
bne %F20 ; No - Take exit path
add r1, r1, #1 ; Otherwise - Increment size unit counter
b %B10 ; and try again
20 cmp r1, #0 ; was any memory detected?
addne r1, r1, #1 ; Yes - bump the increment count by 1
mul r2, r1, r2 ; Calculate total memory size
str r2, [r0] ; Save in base address for later reference
ldmfd sp!, {r3-r4, pc} ; Restore used registers and return to caller
ENDFUNC
;
;*******************************************************************************
;
; **************
; * *
; * BBU_msWait * Subroutine
; * *
; **************
;
; This subroutine is used to generate a delay of r0 milliseconds
;
; PARAMETER PASSING:
;
; r0 = contains the number of milliseconds to delay (preserved).
; MAXIMUM DELAY = 1,321,528 ms (1,321 seconds or 22 min & 1 second)
;
BBU_msWait FUNCTION
stmfd sp!, {r0-r1, lr} ; Save r1 registers & link reg on stack
;
; NOTE: Clock frequency is 3.250 MHz
;
ldr r1, =0xCB2 ; Load r1 with value to generate 1 ms delay
mul r0, r0, r1 ; Calculate the total number of clock ticks
bl BBU_tickWait ; Call the tick wait routine
ldmfd sp!, {r0-r1, pc} ; Restore used registers and return to caller
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -