| |||
| Home > Writing ARM and Thumb Assembly Language > Load and store multiple register instructions > Block copy with LDM and STM | |||
Example 2.11 is an ARM code routine that copies a set of words from a source location to a destination by copying a single word at a time. Refer to Code examples for instructions on how to assemble, link, and execute the example.
Example 2.11. Block copy
AREA Word, CODE, READONLY ; name this block of code
num EQU 20 ; set number of words to be copied
ENTRY ; mark the first instruction to call
start
LDR r0, =src ; r0 = pointer to source block
LDR r1, =dst ; r1 = pointer to destination block
MOV r2, #num ; r2 = number of words to copy
wordcopy LDR r3, [r0], #4 ; load a word from the source and
STR r3, [r1], #4 ; store it to the destination
SUBS r2, r2, #1 ; decrement the counter
BNE wordcopy ; ... copy more
stop MOV pc, lr ; Return to caller
AREA BlockData, DATA, READWRITE
src DCD 1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8,1,2,3,4
dst DCD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
END
This module can be made more efficient by using LDM and STM for
as much of the copying as possible. Eight is a sensible number of
words to transfer at a time, given the number of registers that
the ARM has. The number of eight-word multiples in the block to
be copied can be found (if r2 = number of words to be copied) using:
MOVS r3, r2, LSR #3 ; number of eight word multiples
This value can be used to control the number of iterations through a loop that copies eight words per iteration. When there are less than eight words left, the number of words left can be found (assuming that r2 has not been corrupted) using:
ANDS r2, r2, #7
Example 2.12 lists
the block copy module rewritten to use LDM and STM for copying.
Example 2.12.
AREA Block, CODE, READONLY ; name this block of code
num EQU 20 ; set number of words to be copied
ENTRY ; mark the first instruction to call
start
LDR r0, =src ; r0 = pointer to source block
LDR r1, =dst ; r1 = pointer to destination block
MOV r2, #num ; r2 = number of words to copy
MOV sp, #0x400 ; Set up stack pointer (r13)
blockcopy MOVS r3,r2, LSR #3 ; Number of eight word multiples
BEQ copywords ; Less than eight words to move?
STMFD sp!, {r4-r11} ; Save some working registers
octcopy LDMIA r0!, {r4-r11} ; Load 8 words from the source
STMIA r1!, {r4-r11} ; and put them at the destination
SUBS r3, r3, #1 ; Decrement the counter
BNE octcopy ; ... copy more
LDMFD sp!, {r4-r11} ; Don't need these now - restore
; originals
copywords ANDS r2, r2, #7 ; Number of odd words to copy
BEQ stop ; No words left to copy?
wordcopy LDR r3, [r0], #4 ; Load a word from the source and
STR r3, [r1], #4 ; store it to the destination
SUBS r2, r2, #1 ; Decrement the counter
BNE wordcopy ; ... copy more
stop MOV pc, lr ; Return to caller
AREA BlockData, DATA, READWRITE
src DCD 1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8,1,2,3,4
dst DCD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
END